<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발일지</title>
    <link>https://aszx601.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 10:21:27 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>k1yeee</managingEditor>
    <image>
      <title>개발일지</title>
      <url>https://tistory1.daumcdn.net/tistory/5464648/attach/b5211b7d62994822addfd64e145d0d5a</url>
      <link>https://aszx601.tistory.com</link>
    </image>
    <item>
      <title>Redux 사용이유</title>
      <link>https://aszx601.tistory.com/68</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리덕스 (js의 라이브러리)는 가장 사용률이 높은 상태관리 라이브러리이다. 리덕스를 사용하면, 컴포넌트들의 상태 관련 로직들을 다른 파일들로 분리시켜서 더욱 효율적으로 관리 할 수 있다. 또한, 컴포넌트끼리 상태를 공유하게 될 때 여러 컴포넌트를 거치지 않고도 손쉽게 상태 값을 전달 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로, 리덕스의 미들웨어라는 기능을 통하여 비동기 작업, 로깅 등의 확장적인 작업들을 더욱 쉽게 할 수도 있게 해준다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-13 오후 5.02.58.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgaK0T/btrTtW5Y3es/3iaOIeKfG3ixAwA7sPqVy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgaK0T/btrTtW5Y3es/3iaOIeKfG3ixAwA7sPqVy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgaK0T/btrTtW5Y3es/3iaOIeKfG3ixAwA7sPqVy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgaK0T%2FbtrTtW5Y3es%2F3iaOIeKfG3ixAwA7sPqVy1%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;210&quot; data-filename=&quot;스크린샷 2022-12-13 오후 5.02.58.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림처럼 Redux는&amp;nbsp;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;데이터의 흐름이 단방형으로 흐르는 구조&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;action, reducer, selector, store를 세팅하는 보일러플레이트 코드는 &lt;span style=&quot;color: #f3c000;&quot;&gt;유지보수&lt;/span&gt;라는 장점을 가지고 있지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태의 개수가 적더라도 보일러플레이트 코드가 크다는 단점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redux 라이브러리의 경우&amp;nbsp;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;store에 모든 상태를 저장하는 중앙집중방식&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;store는 외부 요소이기 때문에 리액트 내부에 접근할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 비동기 데이터 처리를 하려면 saga와 같은 별도의 라이브러리를 추가적으로 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Redux는 오직 하나의 store만 가지며, 하나의 객체 트리를 가지기 때문에 디버깅이 용이하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;store 내부 상태는 action 객체에 의해서만 변경이 가능하다. 모든&lt;span&gt;&amp;nbsp;&lt;/span&gt;state 변화들이 하나의 store에만 집중되어 있고 단방향으로 일어나기 때문에 예측 가능한 결과가 나타난다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;reducer는 순수함수이기 때문에 상태를 변경하는 것이 아닌 새로운 상태를 반환한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상태 변화&lt;/b&gt;는 리렌더링을 초래하기 때문에 상태 구성 요소를 최소화하는 것이 좋다. 하지만, SPA에서 시간의 흐름에 따라 상태 구성 요소는 분명 많아질 수 밖에 없다. 리덕스는 결국, 많아진 상태 구성 요소들을 보다 효율적으로 관리할 수 있도록 도와준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스토어&lt;/b&gt;를 사용하여 상태를 컴포넌트 구조 바깥에 두고 스토어라는 중간자를 통해 상태를 업데이트하거나, 새로운 상태를 전달받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 리덕스를 사용하면, 위와 같이 상태값을 컴포넌트에 종속시키지 않고, 상태관리를 바깥에서 할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redux의 단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 코드작성이 '초기에는 복잡'하다. 스테이트 업데이트에 맞는 액션값들과 디스패치함수들 그리고 리듀서들 등등 초기에 미리미리 전부 만들어 줘야하는 복잡성이 있다. 위의 그림은 단 2가지 상태값밖에 없지만 프로젝트가 커지고 복잡해지면 액션값들이 몇십개는 늘어날 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  이 단점을 보완하기위해 여러가지 라이브러리들이 출시되었다. 그중&amp;nbsp;리덕스 툴킷이 제일 유명하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Redux를 사용하면 좋을 경우&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앱의 여러 위치에서 필요한 많은 양의 상태들이 존재할 때 (전역 상태가 필요하다고 느껴질 때)&lt;/li&gt;
&lt;li&gt;상태들이 자주 업데이트 될 때&lt;/li&gt;
&lt;li&gt;상태를 업데이트 하는 로직이 복잡할 때&lt;/li&gt;
&lt;li&gt;앱이 중간 또는 큰 사이즈의 코드를 갖고 있고 많은 사람들에 의해 코드가 관리될 때&lt;/li&gt;
&lt;li&gt;상태가 업데이트되는 시점을 관찰할 필요가 있을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p 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;b&gt;액션&lt;/b&gt;타입을 정의합니다.&amp;nbsp;&lt;b&gt;액션 함수&lt;/b&gt;는 각각의 액션 타입과 파라미터를 입력받아 액션을 객체 형태로 반환해준다. 상태의 변화가 필요해진다면,&amp;nbsp;&lt;b&gt;디스패치&lt;/b&gt;가 액션을 발생시켜&amp;nbsp;&lt;b&gt;스토어&lt;/b&gt;에게 알린다. 스토어로 전달된 액션은 스토어의&amp;nbsp;&lt;b&gt;리듀서 함수&lt;/b&gt;를 호출시키고, 호출된 리듀서 함수는 이전 상태와 액션타입을 파라미터로 전달받아 정의된 로직대로 현재 상태값을 변화시켜 변화된 상태를 반환한다. 반환된 상태는 스토어에 저장된다.&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;+) &lt;b&gt;Flux 란? (mvc 패턴 연관)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flux란 애플리케이션의 데이터 흐름을 관리하는 패턴을 말한다. 중요한 것은 데이터의 흐름이 단방향으로 흐른다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flux 사용이유&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예측가능성을 높여준다.&lt;/li&gt;
&lt;li&gt;데이터의 일관성을 유지하기 쉽게 만들어준다.&lt;/li&gt;
&lt;li&gt;버그를 발견하기 쉽게 해준다.&lt;/li&gt;
&lt;li&gt;테스트를 쉽게 해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flux의 구조&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dispatcher&lt;/li&gt;
&lt;li&gt;Store&lt;/li&gt;
&lt;li&gt;Action&lt;/li&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;/ul&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;+) &lt;b&gt;prop drilling&lt;/b&gt;이란 무엇이고, 어떻게 피할 수 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prop Drilling&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;은 props를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선&lt;span&gt;&amp;nbsp;&lt;/span&gt;Prop Drilling&lt;span&gt;&amp;nbsp;은&lt;/span&gt;&amp;nbsp;문제가 되지 않는다. prop 전달이 3~5개 정도의 컴포넌트라면 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 prop 전달이 10개, 15개 같이 더 많은 과정을 거치게 된다면 어떻게 될까? 코드를 읽을 때 해당 prop을 추적하기 힘들어진다.&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;size18&quot;&gt;그럼 어떻게 해야할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과도한 Prop Drilling를 피하기 위해 전역 상태관리 라이브러리 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Redux, Apollo client, Context API, Recoil 등 상태관리 라이브러리들을 사용한다. 우리가 상태관리할&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;'동적인 information data'&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;들을 어떠한 공간에 모아 그 곳에서 모든 정보를 관리하고 컴포넌트들에게 내려주는 것이다. 이 것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;'스토어'&lt;/b&gt;라고 명칭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전역 상태관리 라이브러리를 사용해 해당 값이 필요한 컴포넌트에서 직접 불러서 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;reference&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://velog.io/@velopert/Redux-1-%EC%86%8C%EA%B0%9C-%EB%B0%8F-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-zxjlta8ywt&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@velopert/Redux-1-%EC%86%8C%EA%B0%9C-%EB%B0%8F-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-zxjlta8ywt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://hannut91.github.io/blogs/flux&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://hannut91.github.io/blogs/flux&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/68</guid>
      <comments>https://aszx601.tistory.com/68#entry68comment</comments>
      <pubDate>Wed, 14 Dec 2022 15:22:08 +0900</pubDate>
    </item>
    <item>
      <title>React vs. Vue vs. Angular</title>
      <link>https://aszx601.tistory.com/67</link>
      <description>&lt;h3 id=&quot;react&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;React&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라이브러리이며 페이스북의 개발자 Jordan Walke가 처음 만들었다. 페이스북에서 지원하며 공동체의 의해 유지보수 된다.&lt;/li&gt;
&lt;li&gt;Virtual Dom 지원&lt;/li&gt;
&lt;li&gt;SSR -&amp;nbsp;&lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;JSX(JavaScritp + XML)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactnative.dev/&quot;&gt;React Native&lt;/a&gt;&amp;nbsp;(앱 개발까지 가능하게 해준다)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리이지만 컴포넌트를 사용한다면, 프레임워크처럼 규칙을 지켜야한다.&lt;br /&gt;장점은&amp;nbsp;&lt;a href=&quot;https://ko.reactjs.org/docs/faq-internals.html&quot;&gt;Virtual Dom&lt;/a&gt;이다. Dom 트리를 추상화하여 자바스크립트 객체로 만들어 두고 변경되는 부분은 virtual dom에서 처리하여 성능을 높혔다.&lt;br /&gt;SPA(Single Page Application) 방식으로 진행한다면 검색엔진 노출(SEO : Search Engine Optimization)에 관련된 문제를 생각 했을 때 SSR을 염두해 둘 수 밖에 없었는데 Next.js를 사용하여 해결 할 수 있다. 그리고 UI를 구성하는 개별적인 뷰 단위인 컴포넌트 단위로 작성하여 생산성과 유지보수에 도움이 된다. JSX(자바스크립트 확장 문법)을 사용하여 컴포넌트를 생성할 수 있다. React Native를 이용해서 앱 개발까지 이어지는 부분이 엄청 큰 메리트가 된다.&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;Vue&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;react와 vue의 차이점에 있어 가장 대표적인 것은, 먼저 react는 UI 라이브러리이며 Vue는 프레임워크라는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;라이브러리&lt;/b&gt;는 참고가 용이하고, 라이브러리의 일부분만 가져와서 사용하는 게 편리하다. 그리고 리액트는 UI 라이브러리이기 때문에 리액트 자체만으로는 전역 상태 관리, 라우팅, 빌드 시스템 등을 지원하지 않는다. 그렇기 때문에 리액트는 별도의 라이브러리를 통해 Redux, Recoil, React-router-dom 등을&amp;nbsp;사용해야 한다. 그렇기 때문에 사용자가 필요할 때에 필요할 때 가져다 쓰고, 빼며 부분적으로 사용이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;반면 뷰는&amp;nbsp;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오픈소스 자바스크립트 프레임워크이며 Google의 전 개발자 Even You가 만들었다. 그를 주축으로 유지보수 중에 있다.&lt;/li&gt;
&lt;li&gt;Virtual Dom 지원&lt;/li&gt;
&lt;li&gt;SSR -&amp;nbsp;&lt;a href=&quot;https://ko.nuxtjs.org/&quot;&gt;Nuxt.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;양방향과 단방향의 바인딩 지원&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kr.vuejs.org/v2/guide/typescript.html&quot;&gt;TypeScript 지원&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nativescript-vue.org/ko/docs/introduction/&quot;&gt;NativeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kr.vuejs.org/v2/guide/single-file-components.html&quot;&gt;Single File Component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;작은 러닝커브(학습 및 적응이 빠름)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React의 장점인 Virtual Dom과 Angular의 양방향 바인딩을 가져왔다는 점에서 볼 때 앞으로도 발전을 기대해 볼 만한 프레임워크라고 생각한다.&lt;br /&gt;자바스크립트의 기본 스타일을 적극적으로 적용하고 있어서 학습하고 적응하기 쉽다.&lt;br /&gt;그리고 Single File Component는&amp;nbsp;.vue&amp;nbsp;파일에 HTML과 CSS 그리고 Script까지 하나로 묶어서 컴포넌트 단위로 직관적인 구성이 가능하다는 것인데, 개인적으로는 파일 분리를 선호하지만 디자이너나 퍼블리셔와 협업하는 과정에서는 생산성이나 유지보수에 큰 도움이 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;angular&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Angular&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;타입스크립트 기반 오픈소스 프레임워크이며 Google에서 만들었고, 지원하며 공동체에 의해 유지보수 중에 있다.&lt;/li&gt;
&lt;li&gt;양방향 바인딩 지원&lt;/li&gt;
&lt;li&gt;TypeScript 기반&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ReactiveX/rxjs&quot;&gt;RxJs&lt;/a&gt;(Reactive Extensions For JavaScript) : 스트림을 통한 비동기 처리 방식 지원&lt;/li&gt;
&lt;li&gt;가장 체계적이고 잘 정리되어있는 문서와 튜토리얼&lt;/li&gt;
&lt;li&gt;큰 러닝커브 (배울 것이 많고 어렵다)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라우팅, 상태관리, 폼 유효성 등 필요한 도구를 모아놓은 All In One 프레임워크인 것이 큰 장점이다. 그렇기 때문인지 React와 Vue.js와 비교했을 때 가장 배울 것이 많고 어려운 편이다. 가볍고 빠르게 작업을 해야하는 프로젝트 보다는 큰 프로젝트에 사용하기 적합하다.&lt;br /&gt;TypeScript를 기반으로 하기 때문에 엄격하지만 그만큼 직관적이고 오류를 줄일 수 있다.&lt;br /&gt;또한 웹사이트가 빠르고 효율적으로 렌더링 되게 설계되어있다. MPA를 구성하기에는 복잡하고, SPA에서는 매우 빠르게 작동한다. 애초에 구글이 SPA를 위해 만든 것이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;angular-의-특징-및-장점&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Angular 의 특징 및 장점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Component 와 Service 단의 분리Angular 에서 Component 는 View 를 처리하는 로직만을 다루며 Service 를 다루는 로직은 분리하여 작성한다. 여기서 사용되는 Service 는 기존의 MVC 패턴에서 사용되는 Service 의 개념과 비슷하다. Component 에서 Service 단 코드를 분리함으로서 코드의 중복성을 줄여주며 유지보수에 용이하게 해준다.&lt;/li&gt;
&lt;li&gt;DOM 조작 방식 : React 와 Vue 는 Virtual DOM 을 활용하여 DOM을 조작하는 반면, Angular 는 &lt;b&gt;Incremental DOM 방식&lt;/b&gt;을 채택하여 DOM 을 조작한다.&lt;/li&gt;
&lt;li&gt;데이터 바운딩 (양방향 바운딩)React 에서는 데이터가 위에서 아래로 흐른다. 즉 부모 컴포넌트에서 자식 컴포넌트에 props 를 흘리는 방식으로 단방향 데이터 바운딩이 이뤄진다. 그에 비해 Angular는 &lt;b&gt;데이터가 양방향으로 흐른다.&lt;/b&gt; 부모 컴포넌트에서 자식 컴포넌트로, 자식 컴포넌트에서 부모 컴포넌트로 데이터를 흘려 보낼 수 있다.&lt;/li&gt;
&lt;li&gt;주력 개발 언어 : Angular의 주력 개발 언어는 Typescript 이다. 이는 Typescript 가 가진 장점을 Angular 을 채택함으로써 그대로 누릴 수 있다는 것이다. Typescript 는 정적 타입 바운딩을 통해서 개발 시 에러를 줄이며, 안정성을 추구하고 자동 완성 기능을 통해 개발자의 개발 경험을 향상 시킨다는 장점이 있다.&lt;/li&gt;
&lt;li&gt;Angular CLI(Command Line Interface) : 앵귤러를 이용하는데 있어서 큰 장점은 CLI 가 아닐까 생각한다. CLI 를 통해서 컴포넌트, 서비스 등 필요한 기능들을 간단하게 생성하고 이용할 수 있다. 그리고 CLI 를 이용하기 때문에 디렉토리의 구조나 코딩 스타일을 획일적으로 유지할 수 있다.&lt;/li&gt;
&lt;li&gt;SSR (Server Side Rendering) 지원Angular 는 SPA 를 위한 프레임 워크이다. SPA 는 CSR 을 기반이지만, Angular 는 SSR 를 위한 기능들을 지원하고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* Virtual DOM 이란?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 는 컴포넌트 별로 가상 DOM 을 만들어 놓고 랜더링 시 새로운 가상 DOM 트리를 생성해 이전의 가상 DOM 과 어떤 차이가 있는지 비교 알고리즘을 통해서 비교 후 변경 사항이나, 새로운 추가 사항이 있을 시 이를 실제 DOM 에 반영하는 식으로 랜더링 한다. 이를 재조정 (Reconcilation) 이라고 하는데 React 에서는 재조정 과정을 하는데 있어서 Fiber 엔진을 사용한다.&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;스크린샷 2022-12-13 오후 2.41.33.png&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;912&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BtkbF/btrTvj6TgEU/alWCzPUvkX0Aakwx4FMto1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BtkbF/btrTvj6TgEU/alWCzPUvkX0Aakwx4FMto1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BtkbF/btrTvj6TgEU/alWCzPUvkX0Aakwx4FMto1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBtkbF%2FbtrTvj6TgEU%2FalWCzPUvkX0Aakwx4FMto1%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;614&quot; height=&quot;396&quot; data-filename=&quot;스크린샷 2022-12-13 오후 2.41.33.png&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;912&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;즉 React 에서는 재조정 과정을 위해서는 메모리에 가상 DOM 을 두 개를 올려야 한다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Incremental 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;&lt;b&gt;Incremental DOM 이란?&lt;/b&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;스크린샷 2022-12-13 오후 2.43.25.png&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgye78/btrTy4g2A7u/lfu4BegRG1SvdxhdD9dxm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgye78/btrTy4g2A7u/lfu4BegRG1SvdxhdD9dxm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgye78/btrTy4g2A7u/lfu4BegRG1SvdxhdD9dxm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbgye78%2FbtrTy4g2A7u%2Flfu4BegRG1SvdxhdD9dxm0%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;687&quot; height=&quot;321&quot; data-filename=&quot;스크린샷 2022-12-13 오후 2.43.25.png&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더링 과정에서 변화를 감지하기 위해 실제 DOM 을 이용하며 변경 사항이 있을 시 이를 즉시 반영한다. Virtual DOM 을 활용할 때 보다 훨씬 메모리 관리에 있어서 효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 Google 의 Angular 팀은 Incremental DOM 을 채택했을까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Angular 팀은 모바일의 발전에 따라서 저용량의 메모리에서도 Application 의 퍼포먼스가 저하되지 않아야 한다고 생각했다. 이를 해결하기 위해서 두 가지 옵션을 최적화 했어야 했는데, 한 가지는 &lt;b&gt;번들링 된 사이즈&lt;/b&gt; 이며, 다른 한 가지는 &lt;b&gt;메모리 관리&lt;/b&gt;였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번들링된 사이즈는 Tree Shaking 을 통해서 해결할 수 있는 이슈이다. Tree-shaking 을 통해서 실제로 DOM 에 반영되지 않을 Component 들은 번들링에서 제외시킨다. 메모리 관리에 있어서는 Incremental DOM 은 추가적인 메모리 공간을 요구하지 않기 때문에 최적화가 가능한 부분이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 Angular 팀은 Incremental 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;h4 id=&quot;angular-의-단점&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Angular 의 단점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 높은 Learning curve&lt;/b&gt;&lt;br /&gt;Angular를 이야기 할 때 보통 러닝 커브가 높다고 이야기 한다. 왜 Angular 의 러닝 커브가 높다고 이야기 하는지 생각해보면, Angular 를 통해서 처음 개발을 접하고자 할 때 진입 장벽이 타 Framework, 혹은 Library 보다 알아야 할 것이 많기 때문이다. Angular 의 Template 문법, CLI, Rxjs, HTTPClient, Routing 등.. 진입 할 때 배워야 할 것이 많아 보인다. 하지만 초기 진입 장벽만 해결한다면, Framework 의 특성상 빠른 속도로 개발하고 유지 보수에 있어서 특화되어 있다는 장점이 있다.&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;edited_스크린샷 2022-12-13 오후 2.48.35.png&quot; data-origin-width=&quot;1535&quot; data-origin-height=&quot;656&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bydS5O/btrTz0ygNEk/6kxisNFatKEQE2vniaKZrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bydS5O/btrTz0ygNEk/6kxisNFatKEQE2vniaKZrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bydS5O/btrTz0ygNEk/6kxisNFatKEQE2vniaKZrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbydS5O%2FbtrTz0ygNEk%2F6kxisNFatKEQE2vniaKZrK%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;691&quot; height=&quot;295&quot; data-filename=&quot;edited_스크린샷 2022-12-13 오후 2.48.35.png&quot; data-origin-width=&quot;1535&quot; data-origin-height=&quot;656&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 자유도 저하&lt;/b&gt;&lt;br /&gt;Angular 는 Framework 이다. Framework 의 특성 상 개발자는 개발 시 일종의 틀에 맞춰서 개발을 해야 하며 이는 개발자가 어느정도의 개발 자유도를 포기해야 함을 의미한다.&lt;/p&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;React 와 비교했을 때 Angular의 차이점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Library or Framework&lt;/li&gt;
&lt;li&gt;Virtual DOM or Incremental DOM&lt;/li&gt;
&lt;li&gt;Facebook or Google&lt;/li&gt;
&lt;li&gt;Ecosystem of these Framework or Library&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;뷰가 진입장벽이 낮고 사용하기 용이함에도 불구하고 NPM 기준으로 React와 view의 주간 다운로드 수는 최대 4배 이상 엄청난 차이가 난다. stackoverflow 차트에서도 react의 사용이 더 많은 것을 확인할 수 있었다. 명확하게 리액트가 월등이 좋다고 할 수는 없지만,&amp;nbsp;진입 장벽이 더 높음에도 불구하고 그만큼 자유도와 typescript의 사용, 변화에 빠른 점, 월등한 사용량으로 인한 시장 크기 차이로 인해 아직 까지 vue가 react를 따라잡기에는 무리가 있어 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;뷰 역시 다양한 장점을 가지고 있고, 국내 유수한 기업에서도 사용하듯 그만의 훌륭한 기능을 가지고 있다. 그렇기 때문에 자신의 프로젝트에 알맞은 라이브러리 또는 프레임워크를 찾아보고 사용하도록 하는 것이 좋을 것이다.&lt;/p&gt;</description>
      <category>React</category>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/67</guid>
      <comments>https://aszx601.tistory.com/67#entry67comment</comments>
      <pubDate>Tue, 13 Dec 2022 15:36:53 +0900</pubDate>
    </item>
    <item>
      <title>런타임(Runtime)과 컴파일타임(Compiletime)의 차이점</title>
      <link>https://aszx601.tistory.com/66</link>
      <description>&lt;h1&gt;런타임(Runtime)과 컴파일타임(Compiletime)의 차이점은 무엇인가?&lt;/h1&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: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://pc.net/helpcenter/answers/compile_time_vs_runtime&quot;&gt;원문보기&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런타임(Runtime)과 컴파일타임(Compiletime)은 소프트웨어 프로그램개발의 서로 다른 두 계층의 차이를 설명하기 위한 용어이다. 프로그램을 생성하기 위해 개발자는 첫째로 소스코드를 작성하고 컴파일이라는 과정을 통해 기계어코드로 변환 되어 실행 가능한 프로그램이 되며, 이러한 편집 과정을 컴파일타임(Compiletime) 이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일과정을 마친 프로그램은 사용자에 의해 실행되어 지며, 이러한 응용프로그램이 동작되어지는 때를 런타임(Runtime)이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;런타임&quot;과 &quot;컴파일 타임&quot;이라는 용어는 종종 서로 다른 두 가지 타입의 에러를 나타내기 위해 사용되어지곤 하는데, 컴파일 타임 에러는 프로그램이 성공적으로 컴파일링되는 것을 방해하는 신택스에러(Syntax error)나 파일참조 오류와 같은 문제를 말하며, 이런 경우 컴파일러는 컴파일 타임 에러를 발생시키고 일반적으로 문제를 일으킨 소스코드 라인을 지시해준다.&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;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴파일타임 오류의 유형&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;신택스 오류&lt;/li&gt;
&lt;li&gt;타입체크 오류&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;런타임 오류의 유형&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0나누기 오류&lt;/li&gt;
&lt;li&gt;널(Null)참조 오류&lt;/li&gt;
&lt;li&gt;메모리 부족 오류&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/66</guid>
      <comments>https://aszx601.tistory.com/66#entry66comment</comments>
      <pubDate>Tue, 13 Dec 2022 15:11:44 +0900</pubDate>
    </item>
    <item>
      <title>웹사이트 성능 최적화 방법 (수정필요)</title>
      <link>https://aszx601.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;마크업 개발자 입장에서 보는 성능 최적화는 크게&amp;nbsp;렌더링 최적화와&amp;nbsp;로딩 최적화&amp;nbsp;두 가지로 나눌 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;성능 최적화 = 렌더링 최적화 + 로딩 최적화&lt;/b&gt;&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 data-ke-size=&quot;size16&quot;&gt;렌더링, 로딩 과정을 종합적으로 최적화 하면 웹 성능을 평가하는핵심적인 웹 지표(LCP,FID,CLS)&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;성능 측정 도구&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lighthouse&lt;/li&gt;
&lt;li&gt;PageSpeed Insights&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  렌더링 최적화&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;CSS 최적화&lt;/b&gt;&lt;/h4&gt;
&lt;p id=&quot;️-리플로우-리페인트reflowrepaint를-고려한-스타일-작성&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;리플로우, 리페인트(Reflow/Repaint)를 고려한 스타일 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리플로우란?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.04.50.png&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9B9zu/btrS0EScOY1/vKke5kAVzUkfpaSvjjDgrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9B9zu/btrS0EScOY1/vKke5kAVzUkfpaSvjjDgrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9B9zu/btrS0EScOY1/vKke5kAVzUkfpaSvjjDgrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9B9zu%2FbtrS0EScOY1%2FvKke5kAVzUkfpaSvjjDgrk%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;1548&quot; height=&quot;214&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.04.50.png&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;브라우저의 스타일이 그려지는 순서이다. 이때 레이아웃의&amp;nbsp;넓이, 높이, 위치 등에 영향을 주는 css 속성을 변경할 경우 'Layout'부터 다시 그려지게 되는데 이를&amp;nbsp;&lt;b&gt;리플로우&lt;/b&gt;(또는 레이아웃)라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리페인트란?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.05.14.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AJAA3/btrS1RjbTYZ/oO0ZohphTKmf3PmyWKpVqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AJAA3/btrS1RjbTYZ/oO0ZohphTKmf3PmyWKpVqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AJAA3/btrS1RjbTYZ/oO0ZohphTKmf3PmyWKpVqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAJAA3%2FbtrS1RjbTYZ%2FoO0ZohphTKmf3PmyWKpVqK%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;1560&quot; height=&quot;220&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.05.14.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반면 레이아웃에 영향을 주지 않는 속성을 변경하면 레이아웃을 건너뛰고 페인트 작업부터 다시 수행하게 되는데 이를&amp;nbsp;&lt;b&gt;리페인트&lt;/b&gt;라고 한다.&lt;/li&gt;
&lt;li&gt;리플로우가 일어나면 브라우저가 전체 픽셀을 다시 계산해야 하기때문에 되도록&amp;nbsp;&lt;b&gt;리페인트&lt;/b&gt;&amp;nbsp;속성을 사용해 스타일을 작성하는 것이 성능면에서 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리플로우를 발생시키는 속성&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;position / width / height / margin / padding / display / top / left / right / bottom / 
box-sizing / border-color / text-align / border / border-width / 
font-family / float / font-size / font-weight / line-height / vertical-align / 
white-space / word-wrap / text-overflow / text-shadow ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리페인트를 발생시키는 속성&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;color / border-style / visibility / background / background-color / 
background-image / background-position / background-repeat / background-size / 
text-decoration / outline / outline-style / outline-color / outline-width / 
border-radius / box-shadow ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;️-리플로우-리페인트reflowrepaint를-고려한-스타일-작성&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;불필요한 CSS 제거&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 말했듯 css는 렌더링 차단 리소스이기 때문에 사용하지 않는 css는 제거하는 것이 좋다. Unused css는 구글 크롬 라이트하우스(Lighthouse)를 통해 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 구글 라이트하우스(Lighthouse)는 2KB 이상 사용되지 않은 css가 있을 시 오류로 표기한다.&lt;/p&gt;
&lt;p data-ke-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; &amp;nbsp;&lt;/b&gt;HTML 최적화&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인라인 스타일을 사용하지 않는다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;html 요소에 style을 통해 인라인 스타일을 작성하면 불필요한 코드 중복이 발생하기 쉽다.&lt;/li&gt;
&lt;li&gt;인라인 스타일은 웹 페이지가 그려지면서 레이아웃에 영향을 미치면서 추가로 리플로우를 발생시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1670400026412&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div style=&quot;margin-top:20px;&quot;&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;!--   --&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;복잡한 DOM 트리 지양&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM 트리가 깊고, 자식 요소가 많을 경우 DOM 트리가 커진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DOM이 작고 깊이가 얕을수록 계산이 빠르다.&lt;/li&gt;
&lt;li&gt;불필요하게 감싸는 요소는 제거한다. (ex. 불필요하게 감싼 div wrapper)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;애니메이션 최적화&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애니메이션을 구현할 때에는 자바스크립트 api, 라이브러리 보다&amp;nbsp;css를 통해 구현하는 것이 성능면에서 이득이다.&lt;/li&gt;
&lt;li&gt;transform은 리플로우와 리페인트 모두 발생시키지 않고 합성만 발생시키는 속성이다.&lt;br /&gt;때문에 애니메이션에서 사용 시 렌더링 속도를 향상시킬 수 있다.&lt;/li&gt;
&lt;li&gt;position 설정 시&amp;nbsp;absolute나&amp;nbsp;fixed로 설정하면 주변 요소에 영향을 주지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;JS 최적화&lt;/b&gt;&lt;/p&gt;
&lt;p id=&quot;️-강제-동기-레이아웃-피하기--레이아웃-스래싱thrashing-피하기&quot; data-ke-size=&quot;size16&quot;&gt;강제 동기 레이아웃 피하기 / 레이아웃 스래싱(thrashing) 피하기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레이아웃 단계가 완료되기 전에 요소의 위치나 크기를 변경 후 바로 가져오려고 하면 강제로 레이아웃이 발생하는데 이것을&amp;nbsp;강제 동기 레이아웃&amp;nbsp;이라고한다.&lt;/li&gt;
&lt;li&gt;그리고 이 레이아웃을 반복적으로 발생시키는 것이&amp;nbsp;레이아웃 스레싱이다.&lt;/li&gt;
&lt;li&gt;JS 최적화에 대해서는&amp;nbsp;&lt;a href=&quot;https://ui.toast.com/fe-guide/ko_PERFORMANCE#%EA%B0%95%EC%A0%9C-%EB%8F%99%EA%B8%B0-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EC%B5%9C%EC%A0%81%ED%99%94&quot;&gt;이곳&lt;/a&gt;의 링크를 첨부한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; &amp;nbsp; 로딩 최적화&lt;/b&gt;&lt;/h3&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 id=&quot;️-css는-head-js는-body-하단에서-불러온다&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;css는 head, js는 body 하단에서 불러온다&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 페이지가 로드되면 html과 css가 동시에 파싱된다. html과 css는 바로 눈에 보이는 시각적 부분을 구현하기때문에 빠르게 그려질수록 좋다. 그래서&amp;nbsp;css는 head 내에서 임포트한다.&lt;/li&gt;
&lt;li&gt;웹 페이지는 파싱을 실행하면서 script를 만나면 html 파싱을 멈추고 해당 파일을 다운로드한 뒤 실행한다. 따라서 js를 제외한 구조들의 로드가 끝나고 js가 들어오는 것이 좋다. 일반적으로&amp;nbsp;body 태그를 닫기 직전에 script를 임포트&amp;nbsp;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 렌더 블로킹(Render Blocking) 이란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Render Blocking 이란 Render를 멈추게 하는 것이고 Render가 멈추면 초기 화면이 늦게 뜨기 때문에 사용자에게 더 좋은 경험을 주려면 Render Blocking 요소를 최소화 하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-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 id=&quot;️-media-속성-사용&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;media 속성 사용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;media&amp;nbsp;속성을 사용하면 조건별로 css를 불러올 수 있다.&lt;/li&gt;
&lt;li&gt;반응형 웹 제작시 유용하게 사용될 수 있다.&lt;/li&gt;
&lt;li&gt;구글 크롬 라이트하우스는(Lighthouse) media 속성이 없는 &amp;lt; link rel=&amp;rdquo;stylesheet&amp;rdquo; &amp;gt;태그를 렌더 블로킹 리소스로 판단한다.&lt;/li&gt;
&lt;li&gt;media&amp;nbsp;속성이 없는 스타일시트는 해당 스타일시트를 브라우저가 해석하는 동안 화면에 스타일을 불러오지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1670402122391&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot;&amp;gt; &amp;lt;!--   --&amp;gt;
&amp;lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot; media=&quot;(min-width:320px) and (max-width:768px)&quot;&amp;gt; &amp;lt;!-- 브라우저의 넓이가 320이상 769미만일때 스타일시트 해석 --&amp;gt;
&amp;lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot; media=&quot;print&quot;&amp;gt; &amp;lt;!-- 프린트할때만 스타일시트 해석 --&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;️-async--defer&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;async / defer&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async와&amp;nbsp;defer&amp;nbsp;속성은 스크립트 파일을 병렬로 다운로드하게 해준다. 즉, 로딩 시 웹페이지 해석을 멈추지 않고 스크립트를 다운로드 하는것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;async는&amp;nbsp;다운로드 후 즉시 실행한다.&lt;/li&gt;
&lt;li&gt;defer는 웹페이지가 모두 그려지고 DOM이 들어왔을 때 스크립트를 실행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1670402184762&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 병렬 다운로드 &amp;amp; 즉시실행 --&amp;gt;
&amp;lt;script async src=&quot;test.js&quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;!-- 병렬 다운로드 &amp;amp; 지연실행 --&amp;gt;
&amp;lt;script defer src=&quot;test.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.36.54.png&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1LOCO/btrS5xD41Cs/5NXkicfGBYRNTEG9tsNkmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1LOCO/btrS5xD41Cs/5NXkicfGBYRNTEG9tsNkmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1LOCO/btrS5xD41Cs/5NXkicfGBYRNTEG9tsNkmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1LOCO%2FbtrS5xD41Cs%2F5NXkicfGBYRNTEG9tsNkmk%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;241&quot; height=&quot;342&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.36.54.png&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;Script&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.37.28.png&quot; data-origin-width=&quot;2054&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGPytJ/btrS4YIYF3m/KufqzTdIXtivUfKgaVxPK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGPytJ/btrS4YIYF3m/KufqzTdIXtivUfKgaVxPK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGPytJ/btrS4YIYF3m/KufqzTdIXtivUfKgaVxPK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGPytJ%2FbtrS4YIYF3m%2FKufqzTdIXtivUfKgaVxPK0%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;2054&quot; height=&quot;282&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.37.28.png&quot; data-origin-width=&quot;2054&quot; data-origin-height=&quot;282&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;lt;Script async&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.38.24.png&quot; data-origin-width=&quot;2068&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ct44zC/btrS1Q5JQ7O/krDHckCxrJ4LK8whTim8EK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ct44zC/btrS1Q5JQ7O/krDHckCxrJ4LK8whTim8EK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ct44zC/btrS1Q5JQ7O/krDHckCxrJ4LK8whTim8EK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fct44zC%2FbtrS1Q5JQ7O%2FkrDHckCxrJ4LK8whTim8EK%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;2068&quot; height=&quot;248&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.38.24.png&quot; data-origin-width=&quot;2068&quot; data-origin-height=&quot;248&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;lt;Script defer&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.39.01.png&quot; data-origin-width=&quot;2060&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCu0kF/btrS0EY3D1n/rAxBFcOlmBeVh5Xpv96rn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCu0kF/btrS0EY3D1n/rAxBFcOlmBeVh5Xpv96rn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCu0kF/btrS0EY3D1n/rAxBFcOlmBeVh5Xpv96rn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCu0kF%2FbtrS0EY3D1n%2FrAxBFcOlmBeVh5Xpv96rn0%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;2060&quot; height=&quot;268&quot; data-filename=&quot;스크린샷 2022-12-07 오후 5.39.01.png&quot; data-origin-width=&quot;2060&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;lt;script&amp;gt;&amp;nbsp;-&amp;nbsp;반드시&amp;nbsp;순서대로&amp;nbsp;실행되어야&amp;nbsp;할때&lt;br /&gt;&amp;lt;script&amp;nbsp;async&amp;gt;&amp;nbsp;-&amp;nbsp;빨리&amp;nbsp;실행되어야&amp;nbsp;할때&lt;br /&gt;&amp;lt;script&amp;nbsp;defer&amp;gt;&amp;nbsp;-&amp;nbsp;마지막에&amp;nbsp;파싱해도&amp;nbsp;상관없을때&lt;br /&gt;&lt;br /&gt;&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;&lt;b&gt;&lt;b&gt;picture 태그 사용&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;a href=&quot;https://velog.io/@hsecode/%EC%B5%9C%EC%A0%81%ED%99%94-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B0%A9%EB%B2%95-5%EB%B6%84-%EC%99%84%EC%84%B1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@hsecode/%EC%B5%9C%EC%A0%81%ED%99%94-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B0%A9%EB%B2%95-5%EB%B6%84-%EC%99%84%EC%84%B1&lt;/a&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670402540606&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;[최적화] 웹 성능 최적화 방법 5분 완성&quot; data-og-description=&quot;성능 최적화 방법 몇가지를 알고 계신가요? 성능 최적화 방법을 아는대로 설명해주세요! ( ...  전부요..? )&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@hsecode/%EC%B5%9C%EC%A0%81%ED%99%94-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B0%A9%EB%B2%95-5%EB%B6%84-%EC%99%84%EC%84%B1&quot; data-og-url=&quot;https://velog.io/@hsecode/최적화-웹-성능-최적화-방법-5분-완성&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bAMG3H/hyQPfj6LuG/vnvYdfcO0I7R2rG3mAPm5k/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/b2uBLD/hyQNUBSmM3/kecpfKGY53U2Zi6kUynfwK/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/y6nzM/hyQNSD4geK/W3DXZLDEFINx6kdtN65GN0/img.png?width=1200&amp;amp;height=606&amp;amp;face=0_0_1200_606&quot;&gt;&lt;a href=&quot;https://velog.io/@hsecode/%EC%B5%9C%EC%A0%81%ED%99%94-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B0%A9%EB%B2%95-5%EB%B6%84-%EC%99%84%EC%84%B1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@hsecode/%EC%B5%9C%EC%A0%81%ED%99%94-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B0%A9%EB%B2%95-5%EB%B6%84-%EC%99%84%EC%84%B1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bAMG3H/hyQPfj6LuG/vnvYdfcO0I7R2rG3mAPm5k/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/b2uBLD/hyQNUBSmM3/kecpfKGY53U2Zi6kUynfwK/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/y6nzM/hyQNSD4geK/W3DXZLDEFINx6kdtN65GN0/img.png?width=1200&amp;amp;height=606&amp;amp;face=0_0_1200_606');&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;[최적화] 웹 성능 최적화 방법 5분 완성&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;velog.io&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;style은 상단, js는 하단에서 불러온다&lt;/li&gt;
&lt;li&gt;웹팩(Webpack) 사용&lt;/li&gt;
&lt;li&gt;js의 공백 줄이기&lt;/li&gt;
&lt;li&gt;html 작성시 불필요한 div를 제거&lt;/li&gt;
&lt;li&gt;css 최적화
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리플로우, 리페인트(Reflow/Repaint)를 고려한 스타일 작성&lt;/li&gt;
&lt;li&gt;사용하지 않는 css 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이미지 최적화
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;picture, img 지연로딩 활용하기&lt;/li&gt;
&lt;li&gt;스프라이트 이미지 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;핵심적인 웹 지표(LCP,FID,CLS) 최적화&lt;/li&gt;
&lt;li&gt;애니메이션은 js보다는 css로 사용한다&lt;/li&gt;
&lt;li&gt;헤더에 만료기한 넣기&lt;/li&gt;
&lt;li&gt;SEO (검색엔진최적화)&lt;/li&gt;
&lt;li&gt;CDN 사용&lt;/li&gt;
&lt;li&gt;Gzip 사용&lt;/li&gt;
&lt;li&gt;파일 개수 줄이기&lt;/li&gt;
&lt;li&gt;라이브러리 의존도 낮추기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://web.dev/optimize-lcp/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://web.dev/optimize-lcp/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670591494179&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;최대 콘텐츠풀 페인트 최적화&quot; data-og-description=&quot;Largest Contentful Paint(최대 콘텐츠풀 페인트, LCP)는 페이지의 메인 콘텐츠가 화면에 모두 렌더링되었을 때를 결정하는 데 사용됩니다. 느린 서버 응답 시간, 리소스 로드 시간, 클라이언트 측 렌더&quot; data-og-host=&quot;web.dev&quot; data-og-source-url=&quot;https://web.dev/optimize-lcp/&quot; data-og-url=&quot;https://web.dev/i18n/ko/optimize-lcp/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dU2Ym1/hyQQp06Xd1/nosKuHS9ZzKZ76Q69fYhyK/img.jpg?width=1200&amp;amp;height=360&amp;amp;face=0_0_1200_360,https://scrap.kakaocdn.net/dn/bafk0e/hyQPcI4RHM/ZCQglhMuSo0TaKNokzAyNk/img.jpg?width=1200&amp;amp;height=360&amp;amp;face=0_0_1200_360,https://scrap.kakaocdn.net/dn/n8YqD/hyQO3ZFYEh/CBl0Y1sWRAPt7vG8LGnJH0/img.jpg?width=3200&amp;amp;height=960&amp;amp;face=0_0_3200_960&quot;&gt;&lt;a href=&quot;https://web.dev/optimize-lcp/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://web.dev/optimize-lcp/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dU2Ym1/hyQQp06Xd1/nosKuHS9ZzKZ76Q69fYhyK/img.jpg?width=1200&amp;amp;height=360&amp;amp;face=0_0_1200_360,https://scrap.kakaocdn.net/dn/bafk0e/hyQPcI4RHM/ZCQglhMuSo0TaKNokzAyNk/img.jpg?width=1200&amp;amp;height=360&amp;amp;face=0_0_1200_360,https://scrap.kakaocdn.net/dn/n8YqD/hyQO3ZFYEh/CBl0Y1sWRAPt7vG8LGnJH0/img.jpg?width=3200&amp;amp;height=960&amp;amp;face=0_0_3200_960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;최대 콘텐츠풀 페인트 최적화&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Largest Contentful Paint(최대 콘텐츠풀 페인트, LCP)는 페이지의 메인 콘텐츠가 화면에 모두 렌더링되었을 때를 결정하는 데 사용됩니다. 느린 서버 응답 시간, 리소스 로드 시간, 클라이언트 측 렌더&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;web.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://web.dev/vitals/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://web.dev/vitals/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670591516360&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;Web Vitals&quot; data-og-description=&quot;정상적인 사이트를 위한 필수 메트릭&quot; data-og-host=&quot;web.dev&quot; data-og-source-url=&quot;https://web.dev/vitals/&quot; data-og-url=&quot;https://web.dev/i18n/ko/vitals/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cbjXh3/hyQPiP2JmZ/BcqAJALrJ9ir8rDVI5ofkk/img.png?width=1200&amp;amp;height=320&amp;amp;face=0_0_1200_320,https://scrap.kakaocdn.net/dn/jISnV/hyQQycFz4j/PZHrIxsC6AD4khrqQTfAO1/img.png?width=1200&amp;amp;height=320&amp;amp;face=0_0_1200_320,https://scrap.kakaocdn.net/dn/cumPVU/hyQQvUx8cV/xtr2Yj7eDjyWm6o1sKROLk/img.png?width=3600&amp;amp;height=960&amp;amp;face=0_0_3600_960&quot;&gt;&lt;a href=&quot;https://web.dev/vitals/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://web.dev/vitals/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cbjXh3/hyQPiP2JmZ/BcqAJALrJ9ir8rDVI5ofkk/img.png?width=1200&amp;amp;height=320&amp;amp;face=0_0_1200_320,https://scrap.kakaocdn.net/dn/jISnV/hyQQycFz4j/PZHrIxsC6AD4khrqQTfAO1/img.png?width=1200&amp;amp;height=320&amp;amp;face=0_0_1200_320,https://scrap.kakaocdn.net/dn/cumPVU/hyQQvUx8cV/xtr2Yj7eDjyWm6o1sKROLk/img.png?width=3600&amp;amp;height=960&amp;amp;face=0_0_3600_960');&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;Web Vitals&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;web.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/62</guid>
      <comments>https://aszx601.tistory.com/62#entry62comment</comments>
      <pubDate>Thu, 8 Dec 2022 01:00:46 +0900</pubDate>
    </item>
    <item>
      <title>JSX 엘리먼트의 key 사용 방법</title>
      <link>https://aszx601.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;공식문서에 의하면,&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;Key&lt;/b&gt;는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;1.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;React가 어떤 항목을 변경, 추가 또는 삭제할지&amp;nbsp;&lt;span&gt;식별하는 것&lt;/span&gt;을 돕고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;엘리먼트에&amp;nbsp;&lt;span&gt;안정적인 고유성을 부여&lt;/span&gt;하기 위해 배열 내부의 엘리먼트에 지정해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span&gt;&amp;ldquo;keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity&quot;.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉 key 는 그 값이 변하지 않는, 유일한 식별자의 역할을 가진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;고유성 부여를 위해 key 값은, 배열의 각 항목 간 서로를 식별할 수 있게하는 문자열을 사용하는 것이 좋다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;대부분 데이터의 ID 를 key 로 사용합니다. (물론 이는 데이터 요소에 ID 프로퍼티가 존재할 때만 가능합니다.)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서는 요소의 리스트를 나열할 때 Key 값을 넣어줘야한다.&lt;br /&gt;Key는 React가 변경, 추가 또는 제거된 항목을 식별하는 데 도움이 된다. 요소에 안정적인 ID를 부여하려면 배열 내부의 요소에 Key를 제공해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 가상 DOM을 이용해 바뀐 부분만을 실제 DOM에 적용하는 데 이때 어떻게 바뀐 부분을 찾을까?&lt;br /&gt;&lt;b&gt;-&amp;gt; Key를 이용해서 어떤 부분이 바뀌었는지 인식하게 된다.&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/61</guid>
      <comments>https://aszx601.tistory.com/61#entry61comment</comments>
      <pubDate>Wed, 7 Dec 2022 16:52:10 +0900</pubDate>
    </item>
    <item>
      <title>JSX 란? (+)</title>
      <link>https://aszx601.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;extensible Markup Language&amp;nbsp;&amp;nbsp;=&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;JSX는 자바스크립트의 확장 문법이다. XML과 매우 비슷하게 생겼으며, 이런 형식으로 작성한 코드는 브라우저에서 실행되기 전에 코드가 번들링 되는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* 바벨이란 ?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 &lt;b&gt;컴파일러&lt;/b&gt;라고 표현할 수 있다. 컴파일러란 인간 수준의 고언어로 작성된 프로그램을 기계어로 된 프로그램으로 출력하는 번역기이다. 하지만 자바스크립트는 컴파일러가 아니라 인터프리터로 동작한다.&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;&lt;b&gt;* 컴파일러 vs. 인터프리터&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일러는 전체 소스를 파악하여 번역을 진행한다면 인터프리터는 소스코드의 각 행을 연속적으로 번역하여 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* 자바스크립트에 어째서 컴파일러 바벨이 필요한가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 바벨이 고레벨 언어를 기계어로 번역하는 게 아닌, 자바스크립트로 결과물을 만들어주는 컴파일러이기 때문이다. 이런걸 소스 대 소스 컴파일러(transpiler)라고 부른다.&lt;/p&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;a href=&quot;https://lihano.tistory.com/20&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://lihano.tistory.com/20&lt;/a&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;XML vs. HTML&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 Markup Language라 생김새는 비슷하지만 큰 차이점이 존재한다. HTML의 태그는 이미 약속한 태그들만 사용 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) &amp;lt;h1&amp;gt;&amp;lt;/h1&amp;gt; 글자 크기 태그&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 XML 태그는 사용자임의로 생성할 수 있다. 그렇다면 XML 태그는 왜 사용자가 임의로 만들게 했을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XML은 어떠한 데이터를 설명하기 위해 이름을 임의로 지은 태그로 데이터를 감싼다. 즉 태그로 데이터 설명을 하는 것이다. 이 부분에서 데이터의 표시(Mark Up)가 되고, 필요한 데이터가 생길 시 태그를 추가하거나 태그 안의 내용을 추가할 수&amp;nbsp; 있다는 특징이 있다.(Extensible)&lt;/p&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;XML 특징&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;XML은 다른 목적의 마크업 언어를 만드는 데 사용되는 다목적 마크업 언어이다.&lt;/li&gt;
&lt;li&gt;XML은 다른 시스템끼리 다양한 종류의 데이터를 손쉽게 교환할 수 있도록 해준다.&lt;/li&gt;
&lt;li&gt;XML은 새로운 태그를 만들어 추가해도 계속해서 동작하므로, 확장성이 좋다.&lt;/li&gt;
&lt;li&gt;XML은 데이터를 보여주지 않고, 데이터를 전달하고 저장하는 것만을 목적으로 한다.&lt;/li&gt;
&lt;li&gt;XML은 텍스트 데이터 형식의 언어로 모든 XML 문서는 유니코드 문자로만 이루어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;XML 문법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;XML문서는 매우 규칙적, 예측이&amp;nbsp;가능한 구조이다.&lt;/li&gt;
&lt;li&gt;모든 XML 요소는 종료 태그를 가져야 한다. 생략되면 오류가 발생.&lt;/li&gt;
&lt;li&gt;대소문자를 구분하여 대소문자가 다르면 다른 요소로 인식한다.&lt;/li&gt;
&lt;li&gt;시작태그와 종료태그의 문자가 동일해야한다. 앞에는 소문자 뒤에는 대문자 불가&lt;/li&gt;
&lt;li&gt;XML은 띄어쓰기를 인식한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;XML 선언&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XML&amp;nbsp;문서는&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;자신에&amp;nbsp;대한&amp;nbsp;정보&amp;nbsp;일부를&amp;nbsp;선언하는&amp;nbsp;것으로&amp;nbsp;시작된다.&lt;/p&gt;
&lt;pre id=&quot;code_1670303008755&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;XML 데이터 예시&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1670303075333&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot; ?&amp;gt;
&amp;lt;note&amp;gt;
  &amp;lt;date&amp;gt;
    &amp;lt;day&amp;gt;07&amp;lt;/day&amp;gt;
    &amp;lt;month&amp;gt;01&amp;lt;/month&amp;gt;
    &amp;lt;year&amp;gt;2021&amp;lt;/year&amp;gt;
  &amp;lt;/date&amp;gt;
  &amp;lt;tistory&amp;gt;
    &amp;lt;title&amp;gt;XML이란&amp;lt;/title&amp;gt;
    &amp;lt;writer&amp;gt;annajang&amp;lt;/writer&amp;gt;
  &amp;lt;/tistory&amp;gt;
  &amp;lt;remark&amp;gt;
    &amp;lt;![CDATA[  CDATA부분에는 &amp;lt; &amp;gt; &amp;amp; &quot; 등과 같은 문자를 그대로 표현할 수 있다  ]]&amp;gt;
  &amp;lt;/remark&amp;gt;
 &amp;lt;/note&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;XML 주석&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&amp;lt;!-- 으로 시작하여 --&amp;gt; 으로 끝난다.&lt;/li&gt;
&lt;li&gt;시작태그에는 느낌표가 있지만 종료 태그에는 느낌표가 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/60</guid>
      <comments>https://aszx601.tistory.com/60#entry60comment</comments>
      <pubDate>Tue, 6 Dec 2022 14:06:31 +0900</pubDate>
    </item>
    <item>
      <title>CSR vs. SSR과 SPA vs. MPA</title>
      <link>https://aszx601.tistory.com/59</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPA(Single Page Application)는 한 개(Single)의 Page로 구성된 Application이다.&lt;br /&gt;MPA(Multiple Page Application)는 여러 개(Multiple)의 Page로 구성된 Application이다.&lt;/li&gt;
&lt;li&gt;MPA는 새로운 페이지를 요청할 때마다 정적 리소스가 다운로드된다. 매번 전체 페이지가 다시 렌더링 된다.&lt;br /&gt;반면 SPA는 웹 에플리케이션에 필요한 모든 정적 리소스를 최초 한 번에 다운로드한다.&lt;br /&gt;그 이후 새로운 페이지 요청이 있을 때, 페이지 갱신에 필요한 데이터만 전달 받아서 페이지를 갱신한다.&lt;/li&gt;
&lt;li&gt;그래서 SPA를 CSR(Client Side Rendering) 방식으로 렌더링한다고 말한다.&lt;br /&gt;그래서 MPA를 SSR(Server Side Rendering) 방식으로 렌더링한다고 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;MPA(Multiple Page Application)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개(Single)의 Page로 구성된 Application이다.&lt;/li&gt;
&lt;li&gt;MPA는 SSR(Server Side Application) 방식으로 렌더링한다.&lt;br /&gt;새로운 페이지를 요청할 때마다 서버에서 렌더링된 정적 리소스(HTML, CSS, JavaScript)가 다운로드된다.&lt;br /&gt;페이지 이동하거나 새로고침하면 전체 페이지를 다시 렌더링한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.25.46.png&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhLJ7n/btrTuABnjKF/GbvXyeArLGseGt0EKk4z60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhLJ7n/btrTuABnjKF/GbvXyeArLGseGt0EKk4z60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhLJ7n/btrTuABnjKF/GbvXyeArLGseGt0EKk4z60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhLJ7n%2FbtrTuABnjKF%2FGbvXyeArLGseGt0EKk4z60%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;644&quot; height=&quot;346&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.25.46.png&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;MPA 장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. SEO 관점에서 유리하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;MPA는 완성된 형태의 HTML 파일을 서버로부터 전달받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 첫 로딩이 매우 짧다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에서 이미 렌더링해서 가져오기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 클라이언트가 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;size18&quot;&gt;&lt;b&gt;MPA 단점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 페이지를 이동하면 깜빡인다. (UX)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매 페이지 요청마다 리로딩(새로고침) 발생.&lt;br /&gt;새로운 페이지를 요청할 때마다 전체 페이지를 다시 렌더링하기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;페이지 이동시 불필요한 템플릿도 중복해서 로딩 (성능)&lt;/li&gt;
&lt;li&gt;서버 렌더링에 따른 부하&lt;/li&gt;
&lt;li&gt;모바일 앱 개발시 추가적인 백엔드 작업 필요 (생산성)개발이 복잡해질 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  SPA(Single Page Application)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 개(Single)의 Page로 구성된 Application이다.&lt;/li&gt;
&lt;li&gt;SPA는 CSR(Client Side Rendering) 방식으로 렌더링한다.&lt;/li&gt;
&lt;li&gt;단 한 번만 리소스(HTML, CSS, JavaScript)를 로딩한다.&lt;br /&gt;그 후에는 데이터를 받아올 때만 서버와 통신한다.&lt;/li&gt;
&lt;li&gt;즉, 첫 요청시 딱 한 페이지만 불러오고 페이지 이동 시 기존 페이지의 내부를 수정해서 보여주는 방식이다.&lt;/li&gt;
&lt;li&gt;이를 클라이언트 관점에서 말하자면 최초 페이지를 로딩한 시점부터는 페이지 리로딩 없이 필요한 부분만 서버로 부터 받아서 화면을 갱신하는 것이다.&lt;br /&gt;필요한 부분만 갱신하기 때문에 네이티브 앱에 가까운 자연스러운 페이지 이동/사용자 경험(UX)을 제공할 수 있다.&lt;/li&gt;
&lt;li&gt;Angular, React, Vue 등 프론트엔드 기술들이 나오면서 크게 유행하고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.34.09.png&quot; data-origin-width=&quot;1042&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ay7eq/btrTtXKv1FQ/kXvQZ62KBEPYmHzXAug1Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ay7eq/btrTtXKv1FQ/kXvQZ62KBEPYmHzXAug1Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ay7eq/btrTtXKv1FQ/kXvQZ62KBEPYmHzXAug1Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAy7eq%2FbtrTtXKv1FQ%2FkXvQZ62KBEPYmHzXAug1Uk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;326&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.34.09.png&quot; data-origin-width=&quot;1042&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그런데 CSR 방식으로 만든 SPA 앱은 검색엔진최적화(SEO)가 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;SPA 장점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자연스러운 사용자 경험 (UX)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 페이지를 업데이트 할 필요가 없기 때문에 빠르고 깜빡거림이 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;필요한 리소스만 부분적으로 로딩 (성능)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPA의 Application은 서버에게 정적리소스를 한 번만 요청한다. 그리고 받은 데이터는 전부 저장해놓는다. (캐시=Cache)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서버의 템플릿 연산을 클라이언트로 분산 (성능)&lt;/li&gt;
&lt;li&gt;컴포넌트별 개발 용이 (생산성)&lt;/li&gt;
&lt;li&gt;모바일 앱 개발을 염두에 둔다면 동일한 API를 사용하도록 설계 가능 (생산성)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;SPA 단점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JavaScript 파일을 번들링해서 한 번에 받기 때문에 초기 구동 속도가 느리다. (Webpack의 code splitting으로 해결 가능)&lt;/li&gt;
&lt;li&gt;검색엔진최적화(SEO)가 어려움 (SSR로 해결 가능)&lt;/li&gt;
&lt;li&gt;보안 이슈 (프론트엔드에 비즈니스 로직 최소화)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SSR에서는 사용자에 대한 정보를 서버측에서 세션으로 관리를 하지만 CSR 방식에서는 클라이언트측의 쿠키말고는 사용자에 대한 정보를 저장할 공간이 마땅치 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPA 방식이 모두 CSR인 것은 아니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;SSR vs. CSR&lt;/b&gt;&lt;/h4&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;size18&quot;&gt;&lt;b&gt;SSR이 렌더링하는 방식&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.43.41.png&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;1068&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/171Zw/btrTzvMmCka/EEZKJ88OgpJ1BIPtvENuv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/171Zw/btrTzvMmCka/EEZKJ88OgpJ1BIPtvENuv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/171Zw/btrTzvMmCka/EEZKJ88OgpJ1BIPtvENuv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F171Zw%2FbtrTzvMmCka%2FEEZKJ88OgpJ1BIPtvENuv1%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;544&quot; height=&quot;1068&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.43.41.png&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;1068&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹에 시작부터 MPA가 있었다. 사실 MPA라는 용어도 SPA와 비교를 위해 등장한 인상이 강하다. 웹의 초기부터 SPA에 대한 구현체들이 나오기 전까지는 전통적인 웹사이트들은 모두 MPA 형태로 서비스해 왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MPA는 페이지를 이동할 때마다 새로운 페이지를 요청한다. 모든 템플릿은 서버 연산을 통해서 렌더링하고 완성된 페이지 형태로 응답한다. 이 과정을 서버 사이드 렌더링(SSR)이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 사이드 렌더링의 장점은 SEO이다. 전통적인 MPA의 경우 브라우저에서 JavaScript 코드가 동작하기 전에도 완성된 형태의 템플릿 (HTML에 데이터가 삽입된 상태)을 서버로 부터 전달받는다. 이 때문에 검색로봇이 페이지를 크롤링하기에 매우 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;CSR이 렌더링하는 방식&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.44.14.png&quot; data-origin-width=&quot;1514&quot; data-origin-height=&quot;1070&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKgKNz/btrTzlJVuhp/e0VEGPubbkHRS0woicrPI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKgKNz/btrTzlJVuhp/e0VEGPubbkHRS0woicrPI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKgKNz/btrTzlJVuhp/e0VEGPubbkHRS0woicrPI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKgKNz%2FbtrTzlJVuhp%2Fe0VEGPubbkHRS0woicrPI1%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;597&quot; height=&quot;1070&quot; data-filename=&quot;스크린샷 2022-12-13 오후 4.44.14.png&quot; data-origin-width=&quot;1514&quot; data-origin-height=&quot;1070&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  SSR CSR 차이&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 초기 렌더링 속도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR은 모든 JS파일을 로드하고 웹을 보여주기 때문에 초기 렌더링 속도는 SSR에 비하여 CSR이 더 느리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이후 나머지 렌더링 속도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 페이지 렌더링 후 페이지와의 상호작용에 의해 다른 페이지로 넘어가는등의 작동을 하게되면, CSR의 경우 이미 나머지를 구성하는 부분의 코드들도 받아 왔지만, SSR은 초기 렌더링 할 때의 과정을 반복하기 때문에 SSR이 상대적으로 더 느리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. SEO&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 엔진은 자동화된 로봇인 '크롤러'로 웹 사이트들을 읽는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR은 자바스크립트를 실행시켜 동적으로 컨텐츠가 생성되기 때문에 자바스크립트가 실행 되어야 meatadata가 바뀌었다.&lt;br /&gt;(이전 크롤러들은 자바스크립트를 실행시키지 않았었기에 SEO 최적화가 필수적이었다. 구글이 그 트렌드를 바꾸고 있다고 한다.)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 보안&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 SSR에서는 사용자에 대한 정보를 서버 측에서 세션으로 관리를 한다. 그러나 CSR 방식은 클라리언트 측의 쿠키 말고는 사용자에 대한 정보를 저장할 공간이 마땅치 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. 서버 자원 사용&lt;/p&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;&amp;nbsp;&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/59</guid>
      <comments>https://aszx601.tistory.com/59#entry59comment</comments>
      <pubDate>Sat, 3 Dec 2022 20:22:37 +0900</pubDate>
    </item>
    <item>
      <title>쿠키 vs. 세션</title>
      <link>https://aszx601.tistory.com/58</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;쿠키 vs. 세션&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿠키와 세션은 비슷한 역할을 하며, 동작 원리도 비슷하다. 그 이유는 세션도 결국 쿠키를 사용하기 때문이다.&lt;/li&gt;
&lt;li&gt;큰 차이점은&amp;nbsp;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;사용자의 정보가 저장되는 위치&lt;/b&gt;&lt;/span&gt;이다.&amp;nbsp;쿠키는 서버의 자원을 전혀 사용하지 않으며,&amp;nbsp;세션은 서버의 자원을 사용한다.&lt;/li&gt;
&lt;li&gt;보안 면에서 세션이 더 우수&lt;/li&gt;
&lt;li&gt;쿠키는&amp;nbsp;클라이언트 로컬에 저장되기 때문에 변질되거나 request에서 스니핑 당할 우려가 있어서&amp;nbsp;보안에 취약하지만&lt;/li&gt;
&lt;li&gt;세션은&amp;nbsp;쿠키를 이용해서 session-id만 저장하고 그것으로 구분하여 서버에서 처리하기 때문에 비교적&amp;nbsp;보안성이 높다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;라이프 사이클&lt;/b&gt;&lt;/span&gt;은 쿠키도 만료기간이 있지만&amp;nbsp;파일로 저장되기 때문에 브라우저를 종료해도 정보가 유지될 수 있다. 또한 만료기간을 따로 지정해&amp;nbsp;쿠키를 삭제할 때까지 유지할 수도&amp;nbsp;있다.&lt;/li&gt;
&lt;li&gt;반면에 세션도 만료기간을 정할 수 있지만,&amp;nbsp;브라우저가 종료되면 만료기간에 상관없이 삭제된다.&lt;/li&gt;
&lt;li&gt;속도 면에서 쿠키가 더 우수하며,&lt;/li&gt;
&lt;li&gt;쿠키는&amp;nbsp;쿠키에 정보가 있기&amp;nbsp;때문에 서버에 요청 시 속도가 빠르고&lt;/li&gt;
&lt;li&gt;세션은 정보가 서버에&amp;nbsp;있기 때문에 처리가 요구되어 비교적 느린 속도를 낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&lt;b&gt;&amp;nbsp;&lt;/b&gt;세션이 쿠키에 비해 보안이 높은 편이나 쿠키를 사용하는 이유는 세션은 서버에 저장되고, 서버의 자원을 사용하기에 서버 자원에 한계가 있고, 속도가 느려질 수 있기 때문에 자원관리 차원에서 쿠키와 세션을 적절한 요소 및 기능에 병행 사용하여&amp;nbsp;서버 자원의 낭비를 방지하며 웹사이트의 속도를 높일 수 있다.&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/58</guid>
      <comments>https://aszx601.tistory.com/58#entry58comment</comments>
      <pubDate>Fri, 2 Dec 2022 01:23:21 +0900</pubDate>
    </item>
    <item>
      <title>[HTML/CSS] 브라우저 렌더링 과정</title>
      <link>https://aszx601.tistory.com/57</link>
      <description>&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML, CSS 파싱해서,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;DOM, CSSOM 트리 구축&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Render 트리 구축&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(DOM 과 CSSOM 을 사용해서 렌더 트리 만듬)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자바스크립트 파싱과 실행&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;레이아웃&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;작업 (&lt;b&gt;트리 배치, 리플로우&lt;/b&gt;) - 각 노드가 화면의 정확한 위치에 표시하기 위해 위치와 크기를 계산하는 과정&lt;/li&gt;
&lt;li&gt;계산된 위치와 크기 등의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;스타일을 실제 픽셀로 표현하는 작업 (Paint)&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;1️⃣-html-파싱과-dom-생성-css-파싱과-cssom-생성&quot; data-ke-size=&quot;size20&quot;&gt;1. HTML 파싱과 DOM 생성, CSS 파싱과 CSSOM 생성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷 주소를 치면, 그 사이트에 알맞는 index.html 파일을 가져오게 된다. 브라우저 렌더링 엔진은 HTML 문서를 파싱해, 브라우저가 이해할 수 있는 자료구조인 DOM 을 생성한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열로 변환되 HTML 문서를 읽고, 이를 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해한다.&lt;/li&gt;
&lt;li&gt;이 토큰들은 다시 객체로 변환해, 노드들을 생성한다. 또한 이 노드들은 트리의 자료구조로 요소 간의 관계를 나타내는데 이러한 노드의 트리 자료구조를 DOM 이라고 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서말한, HTML 파싱을 하다가 CSS 파일을 로드하는 link 태그나 style 태그를 만나면 DOM 생성을 일시중단하고, CSS 파일을 서버로부터 요청하고 HTML 과 동일한 파싱과정을 거쳐 CSSOM 을 생성한다. 이후 CSS 파싱을 전부 완료한 뒤에 다시 HTML 을 파싱해 DOM 생성을 재개한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;2️⃣-렌더-트리-생성&quot; data-ke-size=&quot;size20&quot;&gt;2. 렌더 트리 생성&lt;/h4&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;h4 id=&quot;3️⃣-자바스크립트-파싱과-실행&quot; data-ke-size=&quot;size20&quot;&gt;3. 자바스크립트 파싱과 실행&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;script 태그를 만나면, 마찬가지로 HTML 파싱을 중단하고 자바스크립트 파일을 불러와 자바스크립트 코드를 파싱한다. 자바스크립트 엔진을 이를 해석해, AST(추상적 구문 트리) 를 생성한다. 그리고 AST 를 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트 코드를 생성해 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;4️⃣-리플로우레이아웃-리페인트&quot; data-ke-size=&quot;size20&quot;&gt;4. 리플로우(레이아웃), 리페인트&lt;/h4&gt;
&lt;p id=&quot;리플로우레이아웃&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;리플로우(레이아웃)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저의 뷰포트 내에서 각 노드들의 정확한 위치와 크기를 게산해 배치한다. 브라우저 화면의 어느위치에 어느크기로 출력될지 계산하는 단계이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;리페인트&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;리페인트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소들의 위치와 크기, 스타일 계산이 완료된 Render Tree 를 이용해, 픽셀 값을 채워넣게 된다. 이 때 텍스트, 색, 이미지 ,그림자 효과등이 모두 처리되어 그려진다.&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/57</guid>
      <comments>https://aszx601.tistory.com/57#entry57comment</comments>
      <pubDate>Thu, 1 Dec 2022 18:25:22 +0900</pubDate>
    </item>
    <item>
      <title>웹팩과 바벨</title>
      <link>https://aszx601.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;웹팩(Webpack)&lt;/b&gt;은 의존성을 분석해 모듈을 번들(여러 개를 하나로 묶어주는)시켜주는 역할을 한다. 프로젝트를 개발하다보면 수 많은 라이브러리들을 사용하게 되는데 빌드(build)라는 과정을 통해 하나의 파일로 만들어 준다.&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;웹팩(Webpack)은 모듈을 번들시켜주는 역할을 한다.&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;Node.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;바벨(Babel)&lt;/b&gt;은 코드 변환기다. (자바스크립트의 컴파일러) 세상 사람들은 정말 다양한 종류의 버전의 브라우저를 사용하고 있다. 이건 누가 일괄 업데이트한다고 해결되는 문제도 아니라서 어떤 특정 버전을 딱 맞추기 어렵다. 대부분의 업체에서 최신 버전의 브라우저를 권장하지만 생각보다 이런 일에 관심없는 사람도 많고, 일례로 쇼핑몰과 같이 사람들이 온라인에서 돈을 쓰면서 매출을 올리는 회사들은 구형 브라우저를 쓰는 사람들을 그냥 무시하고 서비스 개발을 진행할수가 없다. 최대한 그 사람들이 불편없이 돈을 쓰고 가도록 만들어 줘야 한다. 하지만 개발자들은 어떤가. 수 십년 지난 브라우저에서만 도는 기능을 위해 지저분한 코드를 작성해야 하거나 최신 기능을 포기해야 하는 일까지 생긴다. 코드가 복잡해지니 당연히 유지보수는 어려워진다. 이런 이유로 개발자들은 최신의 코드를 쓰면서 최대한 많은 사람들이 사용하는데 불편함없이 만들어 주는게 바벨이다. 바벨은 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 코드 자체를 변환시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;바벨은 자바스크립트 컴파일러인데 ECMAScript 2015+코드를 이전의 버전으로 바꿔주는 역할을 한다.&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&gt;바벨은 자바스크립트&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;컴파일러&lt;/span&gt;로&amp;nbsp;&lt;/span&gt;새로운 방식의 자바스크립트로 개발 후,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포할 때에는 예전 방식의 자바스크립트로 변환해서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;배포&lt;/span&gt;하려고 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 사용할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 버젼의 자바스크립트가 실행이 안되는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;구버젼 웹브라우저&lt;/span&gt;를 대응하기 위해서이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ES6 코드를 ES5 코드로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;변환&lt;/span&gt;해주는 일에서 리액트의 JSX문법, 타입스크립트, 코드 압축, Proposal 까지 처리해준다.&lt;/p&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;* 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. 출력&lt;/p&gt;</description>
      <author>k1yeee</author>
      <guid isPermaLink="true">https://aszx601.tistory.com/56</guid>
      <comments>https://aszx601.tistory.com/56#entry56comment</comments>
      <pubDate>Tue, 29 Nov 2022 20:54:29 +0900</pubDate>
    </item>
  </channel>
</rss>