<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>루시오의 Devlog</title>
    <link>https://roothyo.tistory.com/</link>
    <description>개발 관련 지식 포스팅/ 잡담 블로그 입니다. 반갑습니다!
(github : https://github.com/geun9716)
</description>
    <language>ko</language>
    <pubDate>Wed, 22 Jul 2026 02:20:03 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Roothyo</managingEditor>
    <image>
      <title>루시오의 Devlog</title>
      <url>https://tistory1.daumcdn.net/tistory/4056647/attach/417ab3762e2945e089f2d599b2330d2d</url>
      <link>https://roothyo.tistory.com</link>
    </image>
    <item>
      <title>SSL &amp;amp; TLS 및 암호화 방식</title>
      <link>https://roothyo.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;작년부터 올해 초까지 Secure Connection과 Certificate Authentication을 통한 통신 기능에 대해 구현해야 했었는데,&amp;nbsp;당시 SSL에 대해 어렴풋이 알고 있었지만, 실제로 해당 내용을 다뤄보니&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;SSL (Secure Socket Layer) 및 TLS(Transport Layer Security)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, SSL과 TLS에 대해 알아야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP4A4p/btr45k8Qigz/F9astOiC1LMPyBYcbnHjx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP4A4p/btr45k8Qigz/F9astOiC1LMPyBYcbnHjx1/img.png&quot; data-alt=&quot;OSI vs TCP/IP Layers&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP4A4p/btr45k8Qigz/F9astOiC1LMPyBYcbnHjx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP4A4p%2Fbtr45k8Qigz%2FF9astOiC1LMPyBYcbnHjx1%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;341&quot; height=&quot;275&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OSI vs TCP/IP Layers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSL은 TCP/IP 4 Layer 중 전송계층(Transport)상에서 클라이언트와 서버에 대한 인증 및 데이터 암호화를 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응용계층에서부터 TCP 전송계층 사이에서 안전한 채널을 형성해 주는 보안용 프로토콜입니다.&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;NetScape사에서 처음 규약을 만들었으며, 초기 버전들의 많은 결함 때문에, v3.0이 1996년에 Release 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS는 SSL의 v3.0이 기초가되어 v1.0이 만들어 졌으며, TLS가 IETF에서 표준 규약으로 정의되었습니다.&amp;nbsp;엄연히 말하자면 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;TLS는 &lt;/span&gt;SSL을 좀 더 정교하게 만든 것으로 서로 다른 개념이지만, openssl과 같은 명령어를 사용할때는 TLS/SSL 구현체를 사용하기 때문에 함께 취급하는 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;(* openssl v1.0.2이 주로 사용되다가 취약점이 발견되어 v1.1.1 버전으로 업데이트 될때, 비교적 많은 메소드들이 대체 되어서 관리하던 모듈이 빌드가 되지 않고 crash가 발생하여 애를 많이 먹었었다. ex) DTLS )&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;그럼 SSL을 사용하게 된 계기가 무엇 때문이었을까요??&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cR8Ux1/btr5gQLfHLS/3KuiRp8Nxp7SF1vRM8BCtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cR8Ux1/btr5gQLfHLS/3KuiRp8Nxp7SF1vRM8BCtk/img.png&quot; data-alt=&quot;스니핑(Sniffing)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cR8Ux1/btr5gQLfHLS/3KuiRp8Nxp7SF1vRM8BCtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcR8Ux1%2Fbtr5gQLfHLS%2F3KuiRp8Nxp7SF1vRM8BCtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;227&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스니핑(Sniffing)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 스니핑(Sniffing)이라는 공격 때문입니다. 간단히 설명하면 네트워크상에서 자신이 아닌 다른 상대방들의 패킷 교환을 엿듣는 것, 즉 트래픽을 도청하는 과정으로 손쉽게 정보들을 얻을 수 있기 때문이죠, 그래서 HTTP를 사용하는 경우에 만약 클라이언트와 서버 사이의 로그인 과정에서 ID와 Password 혹은 민감한 정보들을 읽을수 있기 때문에, Intra Net에서 사용되는 것이 아닌 이상 HTTPS를 사용하게 되는 것이죠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSL/TLS에는 다양한 특징들이 있습니다.&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;br /&gt;: 클라이언트/ 서버 두 응용 상대방 간에, 연결 전 동적 협상에 의한 보안 연결 수립.&lt;/li&gt;
&lt;li&gt;응용프로그램(Application) 자체 구현 가능.&lt;/li&gt;
&lt;li&gt;계층위치는 응용(Application)계층과 전송(Transport)계층 사이에 위치하나, 전공계층에 보다 밀접, 소켓에 지향적&lt;/li&gt;
&lt;li&gt;TCP / UDP를 프로토콜로 사용하며, 네트워크 Port별로 적용이 가능.&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;그럼 SSL/TLS는 어떤 방식으로 네트워크 패킷을 암호화 할까요??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 알기 위해서는 암&amp;bull;복호화 방식에 대해 알아야합니다. 암호화는 크게 3가지 방식으로 분류됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;패킷 암호화&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대칭키(비공개키) 방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 암&amp;middot;복호화에 동일한 키를 사용하는 방식, 정보 교환 당사자 간에 동일한 키를 공유해야 하므로, 여러 사람과 정보 교환시 많은 키를 유지/관리해야 하는 어려움 존재.&lt;/p&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;br /&gt;: 암&amp;middot;복호화에 쌍을 이룬 서로 다른 키(공개키 - 개인키)를 사용하는 방식. 하나의 키는 공개, 다른 하나는 비공개 하여, 데이터 암호화 속도가 대칭키 암호화 방식에 비해 느리기 때문에 일반적으로 대칭키 암호화 방식의 키 분배 또는 작은 크기의 데이터 암호화에 많이 사용됨.&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;Hash방식&lt;/b&gt;&lt;br /&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;SSL에서는 비대칭키 방식을 통해서 대칭키 방식의 비공개키를 전송자와 수신자 사이의 공유&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(핸드세이크)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;를 하고,공유된 비공개키를 사용하여 대칭키를 사용해 암호화 하는 방식으로 성능과 보안을 동시에 잡는 방식을 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 키를 서로 공유하는 단계에서 '인증서'라고 하는 일종의 서명을 사용하는데, 이는 당신이 신뢰할 수 있는 사람인가를 확인하기 위한 용도로 사용되는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 다음글에서 설명하도록 하겠습니다.&lt;/p&gt;</description>
      <category>ComputerScience/Security</category>
      <category>SSL</category>
      <category>SSL/TLS</category>
      <category>TLS</category>
      <category>네트워크</category>
      <category>대칭키</category>
      <category>보안</category>
      <category>복호화</category>
      <category>비대칭키</category>
      <category>암호화</category>
      <category>인증서</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/95</guid>
      <comments>https://roothyo.tistory.com/95#entry95comment</comments>
      <pubDate>Tue, 21 Mar 2023 21:28:32 +0900</pubDate>
    </item>
    <item>
      <title>VAST란? - (2) VAST &amp;amp; VPAID</title>
      <link>https://roothyo.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글에서 비디오 광고의 종류의 대해서 알아보았습니다. [&lt;a href=&quot;https://roothyo.tistory.com/93&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://roothyo.tistory.com/93&lt;/a&gt;]&lt;/p&gt;
&lt;figure id=&quot;og_1676249340344&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;VAST란? - (1) 비디오 광고 및 종류&quot; data-og-description=&quot;VAST에 대해 알기 위해서는 먼저 비디오 광고와 그 종류들을 알아봐야 한다. 비디오 광고는 동영상이 나오는 환경에서 스트리밍 동영상, 애니매이션, 게임 및 음악 동영상 콘텐츠를 비롯해 다양&quot; data-og-host=&quot;roothyo.tistory.com&quot; data-og-source-url=&quot;https://roothyo.tistory.com/93&quot; data-og-url=&quot;https://roothyo.tistory.com/93&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bpscRN/hyRAqNlwub/Q8PZtvg3F3z135kteOmFj1/img.jpg?width=773&amp;amp;height=578&amp;amp;face=0_0_773_578,https://scrap.kakaocdn.net/dn/kyz8h/hyRAm5aani/tAaUkqMpTZ6oilML5dupd1/img.jpg?width=773&amp;amp;height=578&amp;amp;face=0_0_773_578,https://scrap.kakaocdn.net/dn/r31tA/hyRBSajfry/XG0IPIXIaGKghKfNpOj9K1/img.jpg?width=1400&amp;amp;height=800&amp;amp;face=0_0_1400_800&quot;&gt;&lt;a href=&quot;https://roothyo.tistory.com/93&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://roothyo.tistory.com/93&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bpscRN/hyRAqNlwub/Q8PZtvg3F3z135kteOmFj1/img.jpg?width=773&amp;amp;height=578&amp;amp;face=0_0_773_578,https://scrap.kakaocdn.net/dn/kyz8h/hyRAm5aani/tAaUkqMpTZ6oilML5dupd1/img.jpg?width=773&amp;amp;height=578&amp;amp;face=0_0_773_578,https://scrap.kakaocdn.net/dn/r31tA/hyRBSajfry/XG0IPIXIaGKghKfNpOj9K1/img.jpg?width=1400&amp;amp;height=800&amp;amp;face=0_0_1400_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;VAST란? - (1) 비디오 광고 및 종류&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;VAST에 대해 알기 위해서는 먼저 비디오 광고와 그 종류들을 알아봐야 한다. 비디오 광고는 동영상이 나오는 환경에서 스트리밍 동영상, 애니매이션, 게임 및 음악 동영상 콘텐츠를 비롯해 다양&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;roothyo.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 비디오 광고를 하기 위한 표준인 VAST에 대해서 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;VAST(Vidwo Ad Serving Template)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VAST는 미국 인터넷 광고 협회(IAB, Interactive Advertising &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Bureau&lt;/span&gt;) Tech Lab에서 지정한 비디오 광고 전달 양식 표준입니다. XML 형식으로 Media Player에게 In-Stream 및 Out-Stream 광고의 세부 정보를 전송하는 데 사용됩니다.&amp;nbsp;과거 Video / Audio 광고를 할 때, Media Player의 종류는 너무나 다양하였으며, Player는 1가지 콘텐츠 밖에 재생하지 못하였습니다. 그래서 비디오 광고 재생을 위해 보조 플레이어를 로드하고 원래 콘텐츠를 재생하는 방식을 택하였지만, 이도 버퍼링이 발생하여, 시청자에게 좋은 경험을 제공하지 못했습니다. 이를 해결하기 위한 솔루션으로 광고를 Contents 안에 포함시킨 Inline한 방식을 통해 시청자에게 원활한 광고 경험을 제공합니다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VAST Process - Client Side&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;623&quot; data-origin-height=&quot;263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3jVvm/btrYThp1isb/fMgMib9k1pbfHl8szXaUk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3jVvm/btrYThp1isb/fMgMib9k1pbfHl8szXaUk0/img.png&quot; data-alt=&quot;VAST Process - Client Side&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3jVvm/btrYThp1isb/fMgMib9k1pbfHl8szXaUk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3jVvm%2FbtrYThp1isb%2FfMgMib9k1pbfHl8szXaUk0%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;623&quot; height=&quot;263&quot; data-origin-width=&quot;623&quot; data-origin-height=&quot;263&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VAST Process - Client Side&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. VAST Request&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Player가 광고를 삽입하기 위한 큐에 도달하면, HTTP를 사용하여 광고 요청을 전송한다. 요청은 Publisher의 광고 서버 또는 공급측 플랫폼(supply-side platform)인 광고 서버에 전송됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Wrapper Response&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 서버는 VAST와 함께 Response합니다. 이 Response는 서버가 Ad Request를 채우지 못하면 Inline Response를 전송합니다. 대부분의 Case는 Ad Server가 Wrapper Response를 Response하고, 다른 광고 서버(Secondary Server)로 Player를 Redirect 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Secondary VAST Request&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Wrapper Response를 받으면, Player는 Secondary Request를 Redirect된 광고 서버로 요청을 전달합니다. Secondary Response는 Inline Response 혹은 또 다른 Wrapper Response입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. Inline Response&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 결국, Ad Server는 Inline Response를 제공합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. Inline Execution&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Media Player는 VAST Response를 실행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. Tracking&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: VAST 내부에 Event와 Mapping된 URI로 요청을 보내 광고 재생중의 추적 정보를 광고 서버로 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VAST 형식은 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676252215733&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;VAST version=&quot;2.0&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Ad id=&quot;601364&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;InLine&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;AdSystem&amp;gt;Adsystem Example&amp;lt;/AdSystem&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;AdTitle&amp;gt;VAST 2.0&amp;lt;/AdTitle&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Description&amp;gt;VAST 2.0&amp;lt;/Description&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Error&amp;gt;http://myErrorURL/error&amp;lt;/Error&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Impression&amp;gt;http://myTrackingURL/impression&amp;lt;/Impression&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Creatives&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Creative AdID=&quot;12345&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Linear&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Duration&amp;gt;00:00:30&amp;lt;/Duration&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;TrackingEvents&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;creativeView&quot;&amp;gt;http://myTrackingURL/creativeView&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;start&quot;&amp;gt;http://myTrackingURL/start&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;midpoint&quot;&amp;gt;http://myTrackingURL/midpoint&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;firstQuartile&quot;&amp;gt;http://myTrackingURL/firstQuartile&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;thirdQuartile&quot;&amp;gt;http://myTrackingURL/thirdQuartile&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;complete&quot;&amp;gt;http://myTrackingURL/complete&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/TrackingEvents&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;VideoClicks&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ClickThrough&amp;gt;http://www.examplemedia.com&amp;lt;/ClickThrough&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ClickTracking&amp;gt;http://myTrackingURL/click&amp;lt;/ClickTracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/VideoClicks&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;MediaFiles&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;MediaFile delivery=&quot;progressive&quot; type=&quot;video/x-flv&quot; bitrate=&quot;500&quot; width=&quot;400&quot; height=&quot;300&quot; scalable=&quot;true&quot; maintainAspectRatio=&quot;true&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://demo.examplemedia.com/video/acudeo/Carrot_400x300_500kb.flv
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/MediaFile&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/MediaFiles&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Linear&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Creative&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Creative AdID=&quot;601364-Companion&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CompanionAds&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Companion width=&quot;300&quot; height=&quot;250&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;StaticResource creativeType=&quot;image/jpeg&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://demo.examplemedia.com/vast/this_is_the_ad.jpg
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/StaticResource&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;TrackingEvents&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tracking event=&quot;creativeView&quot;&amp;gt;http://myTrackingURL/tracking&amp;lt;/Tracking&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/TrackingEvents&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CompanionClickThrough&amp;gt;http://www.examplemedia.com&amp;lt;/CompanionClickThrough&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Companion&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Companion width=&quot;728&quot; height=&quot;90&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;StaticResource creativeType=&quot;image/jpeg&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://demo.examplemedia.com/vast/trackingbanner
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/StaticResource&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CompanionClickThrough&amp;gt;http://www.examplemedia.com&amp;lt;/CompanionClickThrough&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Companion&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/CompanionAds&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Creative&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Creatives&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/InLine&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Ad&amp;gt;
&amp;lt;/VAST&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tracking Events : Traking되는 Event의 요청 URI를 제공.&lt;/li&gt;
&lt;li&gt;MediaFiles : 광고 파일의 source&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VMAP (Video Multi Ad Playlist)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 플레이어를 제어할 수 없을 때, 컨텐츠에 표시되는 광고 목록을 통해 컨텐츠를 유지하면서 광고를 정확한 시간에 따라 정의 하는 방식입니다. VMAP을 사용하면 콘텐츠 소유자가 각 휴식 시간의 재생 시점, 사용 가능한 휴식 시간 수, 휴식시간에 허용되는 광고 유형 등의 정보들을 받아와 해당 정보에 따라 비디오 광고를 재생합니다.&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;VMAP Process&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;463&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/shG6a/btrZauAASiO/2qXzkOrnekv5h2n1BKRjG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/shG6a/btrZauAASiO/2qXzkOrnekv5h2n1BKRjG1/img.png&quot; data-alt=&quot;VMAP Process&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/shG6a/btrZauAASiO/2qXzkOrnekv5h2n1BKRjG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FshG6a%2FbtrZauAASiO%2F2qXzkOrnekv5h2n1BKRjG1%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;463&quot; height=&quot;298&quot; data-origin-width=&quot;463&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VMAP Process&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. VMAP Request&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 플레이어가 Primary Server로 VMAP Response를 받기위해 HTTP로 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. VMAP Response&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Primary Server가 Ad Breaks 의 Playlist를 포함한 VMAP Response를 Return 합니다. 각 Ad Break는 VAST Ad response의 형태를 갖습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Play Breaks&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 플레이어는 VMAP에서 지정한 비디오 프로그램내의 Breaks의 광고를 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Tracking URIs Pinges&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 적절한 시간에 비디오 플레이어는 VMAP에 제공된 추적 URI를 요청합니다.&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;VPAID (Video Player Ad Interface Definition)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPYsVw/btrZahnJPEc/m4WBm9sDHe4yNbk37qKMBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPYsVw/btrZahnJPEc/m4WBm9sDHe4yNbk37qKMBK/img.png&quot; data-alt=&quot;VPAID&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPYsVw/btrZahnJPEc/m4WBm9sDHe4yNbk37qKMBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPYsVw%2FbtrZahnJPEc%2Fm4WBm9sDHe4yNbk37qKMBK%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;483&quot; height=&quot;317&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VPAID&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 플레이어와 광고 Unit간의 공통 인터페이스를 설정하여 풍부한 In-Stream 광고 경험을 가능하게 합니다. 이전 글에서 이야기 했듯이 비디오 광고주는 2가지 실행 목표를 갖습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 시청자에게 풍부한 광고 경험을 제공&lt;br /&gt;2. 시청한 광고 경험에 대한 반응 및 사용자 상호 작용 세부 정보 확인.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거 일반적인 비디오 플레이어를 통해 이를 구현하는 건 어려우며, IAB Standard인 VAST를 통해서 1번의 시청자에게 풍부한 광고 경험은 제공하였지만, 상호작용의 확인은 지원하지 않았습니다. 이를 해결하기 위해 Start, FirstQuatile, Pause, Mute, Resume, Skip 등의 여러 Event와 Mapping 된 URI로 Request를 보내는 방식을 통해 2번 목표인 시청자의 Impression을 Tracking 할 수 있게 되었습니다. 당시에는 Tracking 할 수 있는 유일한 방법이었기 때문에 재생을 측정할 수 있는 방법으로 VPAID를 채택하였으나, 최근 VAST 3.0이후에 다다르면서 OMID(Open Measurement Interface Definition)나 SIMID(Secure Interactive Media Interface Definition)을 코드에 사용하는 것을 추천합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPAID의 주의할 점은 많은 경우의 다수의 데이터 수집 VPAID가 페이지 렌더링을 상당히 지연시키고, 시청자에게 부정적인 경험을 제공할수 있는 점이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;437&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ock3x/btrYYpaqFz2/kVDanKMQ3a1K85WxkOKJ31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ock3x/btrYYpaqFz2/kVDanKMQ3a1K85WxkOKJ31/img.png&quot; data-alt=&quot;VPAID Process&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ock3x/btrYYpaqFz2/kVDanKMQ3a1K85WxkOKJ31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOck3x%2FbtrYYpaqFz2%2FkVDanKMQ3a1K85WxkOKJ31%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;389&quot; data-origin-width=&quot;437&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VPAID Process&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 구글에서는 OM SDK를 HTML, Android, iOS 등 여러 플랫폼에서의 OMID를 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.google.com/interactive-media-ads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developers.google.com/interactive-media-ads&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676276060952&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Interactive Media Ads SDKs &amp;nbsp;|&amp;nbsp; Google Developers&quot; data-og-description=&quot;Monetize video, audio, or gaming content with multimedia advertising.&quot; data-og-host=&quot;developers.google.com&quot; data-og-source-url=&quot;https://developers.google.com/interactive-media-ads&quot; data-og-url=&quot;https://developers.google.com/interactive-media-ads&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dDXkxU/hyRBPkFKdl/MERqKRsm2qROgpILLKUxfK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://developers.google.com/interactive-media-ads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.google.com/interactive-media-ads&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dDXkxU/hyRBPkFKdl/MERqKRsm2qROgpILLKUxfK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Interactive Media Ads SDKs &amp;nbsp;|&amp;nbsp; Google Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Monetize video, audio, or gaming content with multimedia advertising.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.google.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;VAST의 예제들을 확인할 수 있는 Inspector 링크입니다. 여러 Inline VAST Response를 시험해 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://googleads.github.io/googleads-ima-html5/vsi/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://googleads.github.io/googleads-ima-html5/vsi/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676276119781&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;IMA HTML5 Video Suite Inspector&quot; data-og-description=&quot;&quot; data-og-host=&quot;googleads.github.io&quot; data-og-source-url=&quot;https://googleads.github.io/googleads-ima-html5/vsi/&quot; data-og-url=&quot;https://googleads.github.io/googleads-ima-html5/vsi/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://googleads.github.io/googleads-ima-html5/vsi/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://googleads.github.io/googleads-ima-html5/vsi/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;IMA HTML5 Video Suite Inspector&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;googleads.github.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;해당 Inspector의 소스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/googleads/googleads-ima-html5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/googleads/googleads-ima-html5&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676276141332&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - googleads/googleads-ima-html5: Samples for the HTML5 IMA SDK.&quot; data-og-description=&quot;Samples for the HTML5 IMA SDK. Contribute to googleads/googleads-ima-html5 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/googleads/googleads-ima-html5&quot; data-og-url=&quot;https://github.com/googleads/googleads-ima-html5&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cmN3Ma/hyRAd1Lh7Q/BppPc4D6jLLkhBrPoUb2T0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/googleads/googleads-ima-html5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/googleads/googleads-ima-html5&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cmN3Ma/hyRAd1Lh7Q/BppPc4D6jLLkhBrPoUb2T0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - googleads/googleads-ima-html5: Samples for the HTML5 IMA SDK.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Samples for the HTML5 IMA SDK. Contribute to googleads/googleads-ima-html5 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/1bBV0JWLZUU&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 :&amp;nbsp; &lt;a href=&quot;https://iabtechlab.com/standards/vast/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://iabtechlab.com/standards/vast/&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>서비스개발(Web, App)</category>
      <category>OMID</category>
      <category>Vast</category>
      <category>videoad</category>
      <category>vmap</category>
      <category>VPAID</category>
      <category>비디오광고</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/94</guid>
      <comments>https://roothyo.tistory.com/94#entry94comment</comments>
      <pubDate>Mon, 13 Feb 2023 17:18:40 +0900</pubDate>
    </item>
    <item>
      <title>VAST란? - (1) 비디오 광고 및 종류</title>
      <link>https://roothyo.tistory.com/93</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;VAST에 대해 알기 위해서는 먼저 비디오 광고와 그 종류들을 알아봐야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비디오 광고는 동영상이 나오는 환경에서 스트리밍 동영상, 애니매이션, 게임 및 음악 동영상 콘텐츠를 비롯해 다양한 콘텐츠가 구동 전, 구동 중, 구동 후에 나오는 광고를 의미한다. (IAB, Interactive Advertising Bureau 미국 인터넷광고협회)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Forbes에 따르면, 마케팅 담당자의 거의 90%가 광고 켐페인에 비디오 광고를 사용하며, 70%의 시청률을 주로 확보할 수 있다.&lt;/p&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;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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;온라인 동영상 광고는 온라인이나 모바일로 제공되는 동영상 광고를 비롯해 유튜브와 같이 임의로 제작된 동영상광고나 PPL 혹은 브랜디드 콘텐츠의 일환으로 진행되는 네이티브 동영상 광고등 여러 종류로 다양해져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 표는 IAB에서 광고가 실리는 콘텐츠의 유형에 따라 온라인 동영상 광고를 분류한 것이다.&lt;/p&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 class=&quot;imageblock&quot;&gt;&lt;span data-url=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot; data-phocus=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot;&gt;&lt;img src=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot; srcset=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 크게 In-Stream Video Ads 와 Out-Stream Video Ads로 나뉜다.&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;In-Stream Video Ads&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&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;Linear Type&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;: 모든 비디오 공간을 차지하여 비디오 콘텐츠와 연속적으로 Inline하게 재생되는 방식. 재생 시점에 따라 Pre-roll, mid-roll, Post-roll로 나뉜다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ESVq6/btrY7LWPduF/R8U4j7GoCPkOQPC4jChc90/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ESVq6/btrY7LWPduF/R8U4j7GoCPkOQPC4jChc90/img.jpg&quot; data-alt=&quot;Pre-roll&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ESVq6/btrY7LWPduF/R8U4j7GoCPkOQPC4jChc90/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FESVq6%2FbtrY7LWPduF%2FR8U4j7GoCPkOQPC4jChc90%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;421&quot; height=&quot;316&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Pre-roll&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kZ56p/btrYUajBBLj/ul5Fz6mckSwRTB9VJ8XU20/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kZ56p/btrYUajBBLj/ul5Fz6mckSwRTB9VJ8XU20/img.jpg&quot; data-alt=&quot;Mid-roll&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kZ56p/btrYUajBBLj/ul5Fz6mckSwRTB9VJ8XU20/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkZ56p%2FbtrYUajBBLj%2Ful5Fz6mckSwRTB9VJ8XU20%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;415&quot; height=&quot;311&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mid-roll&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xJt5q/btrYTWsiZbp/31y888iI1Dy1QkxOMWfd8k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xJt5q/btrYTWsiZbp/31y888iI1Dy1QkxOMWfd8k/img.jpg&quot; data-alt=&quot;Post-roll&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xJt5q/btrYTWsiZbp/31y888iI1Dy1QkxOMWfd8k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxJt5q%2FbtrYTWsiZbp%2F31y888iI1Dy1QkxOMWfd8k%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;407&quot; height=&quot;305&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Post-roll&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Non-Linear Type&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;: 비디오 콘텐츠와 동시에 실행되며, 이러한 광고를 클릭하면 비디오 콘텐츠가 일시 중지되고 전체 플레이어 광고를 표시하거나 사용자를 제품 웹 사이트로 Redirect 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Overlay : 비디오 콘텐츠 위에 하위 20%정도만 가리며, 재생되는 동안 여러 브랜드 제품 광고를 사용할 수 있는 장점이나, 비디오 자막 등 비디오의 다른 정보를 가릴 가능성이 있다는 것이 단점이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8azrs/btrYTWkIvuD/YScIqKuYCKGvn10Awn4nHK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8azrs/btrYTWkIvuD/YScIqKuYCKGvn10Awn4nHK/img.jpg&quot; data-alt=&quot;Overlay Ad&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8azrs/btrYTWkIvuD/YScIqKuYCKGvn10Awn4nHK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8azrs%2FbtrYTWkIvuD%2FYScIqKuYCKGvn10Awn4nHK%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;583&quot; height=&quot;333&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Overlay Ad&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Non-overlay : 비디오 콘텐츠와 동시에 반투명한 화면을 띄우는 등 덜 가린채로 광고하는 방식.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwVQk9/btrYUS3fZTu/21GU1RU7dbaBc0R5kRLLX0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwVQk9/btrYUS3fZTu/21GU1RU7dbaBc0R5kRLLX0/img.jpg&quot; data-alt=&quot;Non-overlay Ad&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwVQk9/btrYUS3fZTu/21GU1RU7dbaBc0R5kRLLX0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwVQk9%2FbtrYUS3fZTu%2F21GU1RU7dbaBc0R5kRLLX0%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;576&quot; height=&quot;329&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Non-overlay Ad&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Out-Stream Video Ads&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;In-Page&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 콘텐츠나 다른 스트리밍 자료가 첨부되지 않은 웹 페이지에 비디오 광고를 배치하는 방식. 많은 양의 공간을 요구하지만 작게 배치를 제공할 수 있음.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4UKSJ/btrYSpVvMsv/dSUif9CjtF5w4AyNYzMf6K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4UKSJ/btrYSpVvMsv/dSUif9CjtF5w4AyNYzMf6K/img.jpg&quot; data-alt=&quot;In-Page Video Ad&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4UKSJ/btrYSpVvMsv/dSUif9CjtF5w4AyNYzMf6K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4UKSJ%2FbtrYSpVvMsv%2FdSUif9CjtF5w4AyNYzMf6K%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;636&quot; height=&quot;363&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;In-Page Video Ad&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In-Banner&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 콘텐츠가 웹페이지에서 실행되도록하는 일반적인 크기의 배너 비디오 광고.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBXu77/btrYT8SPccz/kz7zftMeTUk8YfJxNjLeNK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBXu77/btrYT8SPccz/kz7zftMeTUk8YfJxNjLeNK/img.jpg&quot; data-alt=&quot;In-Banner Video Ad&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBXu77/btrYT8SPccz/kz7zftMeTUk8YfJxNjLeNK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBXu77%2FbtrYT8SPccz%2Fkz7zftMeTUk8YfJxNjLeNK%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;666&quot; height=&quot;381&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;In-Banner Video Ad&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In-Text&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 웹 페이지의 텍스트 내용 내의 비디오 광고가 스크롤 되는 것에 트리거 되는 광고 방식. 50% 이상 화면에 보이면 비디오가 시작하고, 50% 이하로 화면에서 나가면 비디오가 정지된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clJf4J/btrYTOturhx/l5OqzdHVvw6EOWCy93NXr1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clJf4J/btrYTOturhx/l5OqzdHVvw6EOWCy93NXr1/img.jpg&quot; data-alt=&quot;In-Text Video Ad&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clJf4J/btrYTOturhx/l5OqzdHVvw6EOWCy93NXr1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclJf4J%2FbtrYTOturhx%2Fl5OqzdHVvw6EOWCy93NXr1%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;674&quot; height=&quot;385&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;In-Text Video Ad&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In-Companion&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 비디오 콘텐츠와 함께 실행되어 동반되는 광고방식이다. 배너, 오버레이등 &lt;span&gt;다양한 크기 및 형식으로&lt;span&gt; 제공됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mMDyk/btrYV8Y4YRv/XM6RFPFqDV1nUZXw6XmUV1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mMDyk/btrYV8Y4YRv/XM6RFPFqDV1nUZXw6XmUV1/img.jpg&quot; data-alt=&quot;In-companion ads&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mMDyk/btrYV8Y4YRv/XM6RFPFqDV1nUZXw6XmUV1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmMDyk%2FbtrYV8Y4YRv%2FXM6RFPFqDV1nUZXw6XmUV1%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;684&quot; height=&quot;391&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;In-companion ads&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;다음은 이러한 비디오 광고를 규격화한 VAST에 대해서 적어보도록 하겠다.&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://oko.uk/blog/video-ad-formats&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://oko.uk/blog/video-ad-formats&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://rocketium.com/academy/video-ads-marketers-must-know/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://rocketium.com/academy/video-ads-marketers-must-know/&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://blog.naver.com/kpfjra_/222096202780&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.naver.com/kpfjra_/222096202780&lt;/a&gt;]&lt;/p&gt;</description>
      <category>서비스개발(Web, App)</category>
      <category>In-Stream</category>
      <category>Out-Stream</category>
      <category>Vast</category>
      <category>Video Ads</category>
      <category>vmap</category>
      <category>VPAID</category>
      <category>비디오광고</category>
      <category>비디오광고종류</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/93</guid>
      <comments>https://roothyo.tistory.com/93#entry93comment</comments>
      <pubDate>Sat, 11 Feb 2023 14:30:29 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 베스트앨범 - JavaScript</title>
      <link>https://roothyo.tistory.com/92</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문제 설명&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.&lt;/p&gt;
&lt;ol 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;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요.&lt;/p&gt;
제한사항
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;genres[i]는 고유번호가 i인 노래의 장르입니다.&lt;/li&gt;
&lt;li&gt;plays[i]는 고유번호가 i인 노래가 재생된 횟수입니다.&lt;/li&gt;
&lt;li&gt;genres와 plays의 길이는 같으며, 이는 1 이상 10,000 이하입니다.&lt;/li&gt;
&lt;li&gt;장르 종류는 100개 미만입니다.&lt;/li&gt;
&lt;li&gt;장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.&lt;/li&gt;
&lt;li&gt;모든 장르는 재생된 횟수가 다릅니다.&lt;/li&gt;
&lt;/ul&gt;
입출력 예
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;genres&lt;/td&gt;
&lt;td&gt;plays&lt;/td&gt;
&lt;td&gt;return&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[&quot;classic&quot;, &quot;pop&quot;, &quot;classic&quot;, &quot;classic&quot;, &quot;pop&quot;]&lt;/td&gt;
&lt;td&gt;[500, 600, 150, 800, 2500]&lt;/td&gt;
&lt;td&gt;[4, 1, 3, 0]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
입출력 예 설명
&lt;p data-ke-size=&quot;size16&quot;&gt;classic 장르는 1,450회 재생되었으며, classic 노래는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고유 번호 3: 800회 재생&lt;/li&gt;
&lt;li&gt;고유 번호 0: 500회 재생&lt;/li&gt;
&lt;li&gt;고유 번호 2: 150회 재생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pop 장르는 3,100회 재생되었으며, pop 노래는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고유 번호 4: 2,500회 재생&lt;/li&gt;
&lt;li&gt;고유 번호 1: 600회 재생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 pop 장르의 [4, 1]번 노래를 먼저, classic 장르의 [3, 0]번 노래를 그다음에 수록합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장르 별로 가장 많이 재생된 노래를 최대 두 개까지 모아 베스트 앨범을 출시하므로 2번 노래는 수록되지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 공지 - 2019년 2월 28일 테스트케이스가 추가되었습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 효율성 문제에서 조금 더 수정할 필요는 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Python으로 풀던 문제를 JS로 풀려다 보니 익숙해지려면 조금 시간이 걸릴거 같고 JS 스럽게 코드를 짜는 것도 더 노력해야할 것 같다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1658205632754&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(genres, plays) {
    var answer = [];
    var cnt = {}
    var obj = {}
    for(let [idx, el] of genres.entries()){
        console.log(idx, el)
        cnt[el] = cnt[el]?cnt[el]+plays[idx]:plays[idx]
        if (el in obj){
            obj[el].push([plays[idx], idx])
        } else {
            obj[el] = [[plays[idx], idx]]
        }
    }
    return Object.entries(cnt)
        .sort(([, a], [, b]) =&amp;gt; b - a)
        .reduce((arr, key)=&amp;gt;{
        return arr.concat(obj[key[0]].sort((a, b)=&amp;gt;b[0]-a[0]).slice(0, 2).map(item=&amp;gt;item[1]))
    }, []);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>ComputerScience/코딩테스트</category>
      <category>HASH</category>
      <category>JavaScript</category>
      <category>js</category>
      <category>프로그래머스</category>
      <category>해쉬</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/92</guid>
      <comments>https://roothyo.tistory.com/92#entry92comment</comments>
      <pubDate>Tue, 19 Jul 2022 13:42:59 +0900</pubDate>
    </item>
    <item>
      <title>CSR vs SSR (Rendering 기법의 차이)</title>
      <link>https://roothyo.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 Server Side Rendering과 Client Side Rendering의 차이점을 공유하고자 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상반된 관계에 있는 방식인 만큼 장단점이 서로 엇갈려서 서로의 장단을 정확하게 알고 적재적소에 필요한 방식으로 구현하는 것이 중요하다고 생각합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SSR (Server Side Rendering)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR은 서버측에서 렌더링이 되고 나온 결과물을 클라이언트에 전달하는 방식을 의미합니다.&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;User가 WebSite 요청을 보냅니다.&lt;/li&gt;
&lt;li&gt;Server는 'Ready To Render'. 즉, 즉시 렌더링 가능한 html 파일을 만듭니다.&lt;/li&gt;
&lt;li&gt;렌더링 된 HTML과 함께 클라이언트가 자바 스크립트를 다운받습니다.&lt;/li&gt;
&lt;li&gt;다운 받아지고 있는 사이에 유저는 컨텐츠는 볼 수 있지만, 사이트를 조작할 수는 없습니다.&lt;/li&gt;
&lt;li&gt;브라우저가 JavaScript 프레임 워크를 실행합니다.&lt;/li&gt;
&lt;li&gt;성공적으로 컴파일 되었기 때문에 사용자 조작 및 웹 페이지와의 상호작용이 가능해집니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CSR (Client Side Rendering)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR은 렌더링이 클라이언트 쪽에서 일어납니다. 즉, 서버가 요청을 받으면 클라이언트에 HTML과 JS를 전송합니다.&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp;User가 WebSite 요청을 보냅니다.&lt;/li&gt;
&lt;li&gt;CDN이 HTML파일과 JS로 접근할 수 있는 링크를 클라이언트로 보냅니다.&lt;/li&gt;
&lt;li&gt;클라이언트는 HTML과 JS를 다운로드 받습니다.&lt;/li&gt;
&lt;li&gt;다운이 완료된 JS가 실행되면서 데이터를 받아 오기 위한 API가 호출됩니다.&lt;/li&gt;
&lt;li&gt;서버가 API 요청으로부터 data를 전송하면, Client는 placeholder 자리에 데이터를 넣어주게되고 페이지는 상호작용이 가능해집니다.&lt;/li&gt;
&lt;/ol&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 vs CSR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 서로 어떤 장단점이 있고, 어떤 상황에서 적용해야 할까요??&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;SSR&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;CSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;첫 페이지 로딩 시간&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;SSR은 필요한 부분의 HTML과 스크립트만 불러오게 되므로 비교적 빠름&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;모든 HTML, CSS와 스크립트를 한번에 불러오므로 비교적 느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;페이지 이동 로딩 시간&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;필요한 부분의 HTML과 스크립트를 그때그때 받아오기 때문에 비교적 느림&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;모든 HTML, CSS와 스크립트를 한번에 받아왔기 때문에 비교적 빠름.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;SEO (Search Engine Optimization) 대응&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;서버 사이드에서 컴파일 되어 클라이언트로 넘어오기 때문에 크롤러에 대응하기 용이&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;자바스크립트가 동적으로 컨텐츠를 생성하기 때문에 추가적인 SEO 최적화가 필수적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;자원 사용&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;서버에서 렌더링을 진행하기 때문에, 서버 자원 사용&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;클라이언트에서 렌더링을 진행하기 때문에 클라이언트 자원을 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR&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;SEO가 필요할 때&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;CSR&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;SEO에 관심이 없을 때&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;주로 React 프레임워크인 Next.js는 SSR를 제공하면서 부분적인 CSR을 적용할 수 있다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 Next.js가 제공해주는 기능을 보도록하겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Automatic Routing : 페이지 기반 라우팅 시스템&lt;/li&gt;
&lt;li&gt;pre-Rendering : 페이지 별 정적 파일 생성과 서버 사이드 렌더링 지원&lt;/li&gt;
&lt;li&gt;Code Spliting : Dynamic import를 이용하여 손쉽게 코드 스플리팅이 가능합니다.&lt;/li&gt;
&lt;li&gt;pre-Fetch 기능을 갖는 CSR&lt;/li&gt;
&lt;li&gt;CSS, SASS 기본 지원 및 다른 CSS-in-JS 라이브러리 지원&lt;/li&gt;
&lt;li&gt;HMR(HOT Module Replacement) 지원&lt;/li&gt;
&lt;li&gt;서버 없이 API 끝단 라우팅 지원 (API routes to build API endpoints with Serverless Function)&lt;/li&gt;
&lt;li&gt;SEO 지원 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>서비스개발(Web, App)/Front-End</category>
      <category>csr</category>
      <category>Next.js</category>
      <category>rendering</category>
      <category>SEO</category>
      <category>SSR</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/91</guid>
      <comments>https://roothyo.tistory.com/91#entry91comment</comments>
      <pubDate>Tue, 19 Jul 2022 00:59:49 +0900</pubDate>
    </item>
    <item>
      <title>TLS(Transport Layer Security) 알고리즘 (HTTPS &amp;amp; SSL )</title>
      <link>https://roothyo.tistory.com/90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 서비스에서 주로 사용되는 HTTP는 암호화 되지 않은 평문을 데이터로 전달하게 되는데, 통신이 되는 도중에 패킷을 훔쳐보는 *스니핑 공격에 대응하기 위해서 TLS를 적용합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스니핑(Sniffing)&lt;br /&gt;네트워크 상에서 자신이 아닌 다른 상대방들의 패킷 교환을 엿듣는 것&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS(전송 계층 보안)은 웹에서 암호화를 구현하는데 가장 널리 사용되는 프로토콜입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS는 암호화 프로세스의 조합을 사용하여 네트워크를 통한 보안 통신을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS가 있는 TCP/IP 프로토콜 스택은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP -&amp;gt; TLS -&amp;gt; TCP -&amp;gt; IP 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS는 보안과 성능상 이슈로 두 가지의 암호화 방법을 혼용해서 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 대칭키 암호화 (Symmetric key algorithm)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 비대칭키 암호화 (Asymmetric key algorithm)&lt;/b&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;/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;하지만 이 대칭키를 상대방과 내가 서로 공유를 해야하는데, 대칭키를 상대에게 전달하는 방식에서 해킹을 당한다면 데이터가 노출될 수 있습니다.&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 대칭키 암호화의 근본적인 문제를 해결하고자 나온 것이 비대칭키 암호화 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 키를 갖는 대칭키 암호화 방식과 달리, 비대칭키 암호화 방식은 한 쌍의 키(공개 키와 개인 키)를 갖게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;한쌍의 키로 암호화 복호화를 하는 방식을 RSA 알고리즘이라고 합니다.&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;하지만 TLS는 대칭키 방식과 비대칭키 방식을 같이 사용하는 이유는 무엇일까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RSA 알고리즘을 이용한 암호화 방식은 복잡한 수학적 원리로 이루어져 있어, CPU 리소스를 크게 소모한다는 단점이 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 TLS의 암호화 방식은 결국 처음에 대칭키를 공유하는 통신을 비대칭키 방식을 이용하고, 실제 통신을 할 때는 CPU 리소스 소모가 적은 대칭키 방식으로 데이터를 주고 받습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 TLS가 제공하는 이점은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;기밀성 (암호화)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 무결성&lt;/b&gt; : 통신 도중 데이터가 제 3자에 의해 변경될 일이 없다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서버 인증&lt;/b&gt; : 신뢰할 수 있는 서버이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 TLS 기법을 사용하기 위해서 CA 기관으로 부터 공개키와 암호키를 발급 받아야 합니다.&lt;/p&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;CA(Certificate Authority)&lt;/b&gt;는 인증서를 발급해 주는 기관입니다. 아무 기업이나 할 수 있는 것이 아닌 신뢰성이 엄격하게 공인된 기업들 만이 진행할 수 있습니다. 이렇게 CA는 자체적으로 발급한 공개키와 개인키가 존재합니다.&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;CA 인증서 발급 과정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. A회사에서 CA로 부터 도메인 등 여러 정보를 포함하여 인증서 발급을 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. A회사에 대해 검증을 거친 후, CA의 공개키를 이용하여 발급 하고자 하는 회사의 공개키를 해싱(SHA-256 등)합니다.&lt;br /&gt;-&amp;gt; '지문'으로 등록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 앞서 등록한 해시(지문)를 CA의 개인키로 암호화 하여 인증서에 '서명'으로 등록합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 서버에게 디지털 서명, 발급자 정보 등이 등록되어 있는 인증서를 발급해줍니다. -&amp;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;TLS 암호화 과정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 클라이언트는 브라우저에 신뢰하고 있는 CA 리스트들과 함께 그들의 공개키도 갖고있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 클라이언트가 서버에 접속하기 위해서 handshake가 이루어지면 서버는 자신의 인증서와 공개키를 클라이언트에 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서버로 부터 받은 인증서를 자신이 가진 CA 리스트에 있는 기관에서 발급받은 것인지 확인하기 위해서 해당 CA 기관의 공개키로 서버 인증서의 서명을 복호화 합니다.&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. 서로 공유한 대칭키를 통해서 암호화된 데이터를 송수신 합니다.&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;다음은 TLS 통신을 Sequence Diagram으로 간단히 도식한 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MMnao/btrHCxB2l49/Ii5OJNUpmeVv53WHaUYQbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MMnao/btrHCxB2l49/Ii5OJNUpmeVv53WHaUYQbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MMnao/btrHCxB2l49/Ii5OJNUpmeVv53WHaUYQbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMMnao%2FbtrHCxB2l49%2FIi5OJNUpmeVv53WHaUYQbK%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;393&quot; height=&quot;341&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;341&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;더 자세한 내용은 아래에 첨부된 oracle 공식 docs 링크를 참조하기를 추천드립니다.&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;a href=&quot;https://babbab2.tistory.com/4?category=960153&quot;&gt;https://babbab2.tistory.com/4?category=960153&lt;/a&gt;]&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&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/tls.html&quot;&gt;https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/tls.html&lt;/a&gt;]&lt;/p&gt;</description>
      <category>ComputerScience/네트워크</category>
      <category>ca</category>
      <category>https</category>
      <category>SSL</category>
      <category>TLS</category>
      <category>TSL알고리즘</category>
      <category>개인키</category>
      <category>공개키</category>
      <category>비대칭키</category>
      <category>암호화</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/90</guid>
      <comments>https://roothyo.tistory.com/90#entry90comment</comments>
      <pubDate>Mon, 18 Jul 2022 17:36:56 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript - 이벤트 루프(Event Roop) [런타임 모델]</title>
      <link>https://roothyo.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript의 런타임 모델은 코드의 실행, 이벤트의 수집과 처리, 큐에 대기중인 하위 작업을 처리하는 이벤트 루프에 기반하고 있습니다.&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;295&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M2ySJ/btrG8H6QJis/YAHvw7vKNe1sAPv02Wpps0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M2ySJ/btrG8H6QJis/YAHvw7vKNe1sAPv02Wpps0/img.jpg&quot; data-alt=&quot;JavaScript 런타임 모델&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M2ySJ/btrG8H6QJis/YAHvw7vKNe1sAPv02Wpps0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM2ySJ%2FbtrG8H6QJis%2FYAHvw7vKNe1sAPv02Wpps0%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;295&quot; height=&quot;271&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;JavaScript 런타임 모델&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;스택&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수의 호출들은 '프레임' 스택을 형성합니다. 인수와 지역 변수는 스택 바깥에 저장되므로 바깥 함수가 반환한 후에도 계속 존재할 수 있습니다. &lt;b&gt;클로저 환경이 중첩 함수에서 지역 변수에 접근할 수 있는 이유가 이것 입니다.&lt;/b&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 힙에 할당됩니다. 힙은 단순히 메모리의 큰(그리고 대부분 구조화되지 않은) 영역을 지칭하는 용어입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;큐&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 런타임은 &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;런타임은 대기열에서 가장 오래된 메시지부터 큐에서 꺼내 처리하기 시작합니다. 이를 위해 꺼낸 메시지를 매개변수로, 메시지에 연결된 함수를 호출합니다. 다른 함수와 마찬가지로 호출로 인한 새로운 스택 프레임도 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 처리는 스택이 다시 텅 빌 때까지 계속됩니다. 그 후, 큐에 메시지가 남아 있으면 같은 방법으로 처리를 계속 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 루프는 기능을 구현할 때 사용하는 방식에서 그 이름을 얻었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657676193154&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(queue.waitForMessage()){
	queue.processNextMessage();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;queue.waitForMessage() 함수는 현재 처리할 수 있는 메시지가 존재하지 않으면 새로운 메시지가 도착할 때까지 동기적으로 대기합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 루프는 Call Stack이 비어있을 때, Queue의 작업을 stack으로 옮겨 줍니다.&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;setTimeout 함수는 이벤트루프를 확인하기 좋은 예제입니다. 매개변수로 큐에 추가할 콜백함수(메시지)와 시간 값을 갖습니다. 아래 예제에서 두번째 매개 변수 값을 주지 않으면 0초가 기본 값이기 때문에 바로 실행될 것 같지만, 결과는 즉시 실행되지 않는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657676384189&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(function() {

  console.log('시작');

  setTimeout(function cb() {
    console.log('콜백 1: 콜백 메시지');
  }); // has a default time value of 0

  console.log('평범한 메시지');

  setTimeout(function cb1() {
    console.log('콜백 2: 콜백 메시지');
  }, 0);

  console.log('종료');

})();

// &quot;시작&quot;
// &quot;평범한 메시지&quot;
// &quot;종료&quot;
// &quot;콜백 1: 콜백 메시지&quot;
// &quot;콜백 2: 콜백 메시지&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백함수로 온 메시지는 큐에 들어가기 때문에, 호출된 함수들이 스택에서 모두 완료가 되면 이후에 큐에 있는 이벤트를 처리하게 되는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 언어와 달리 JavaScript는 blocking 연산을 하지 않습니다. Non-Blocking은 이벤트 루프 모델의 흥미로운 특징으로 대부분의 입출력 처리가 이벤트와 콜백을 통해 수행되므로 애플리케이션이 IndexedDB 질의나 XHR 요청의 반환을 대기 중이더라도 여전히 사용자 입력 등 다른 것들을 처리할 수 있는 것입니다.&lt;/p&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;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;전통적으로 JavaScript는 짧고 빠르게 실행되는 코드를 위한 것이었습니다. 복잡한 작업을 수행하면서 오랜 시간 브라우저에서 실행되는 구조가 아닌 서버에서 주로 계산하여 보여주기 위함이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;더군다나 멀티쓰레드를 지원하는 언어의 경우 동기화(synchronized) 문제에 대해 많은 신경을 쓰고 있는데, JavaScript와 같이 변수의 형태와 추가가 자유로운 언어에서 동기화를 지원하기 까다로울 뿐더러, 이미 웹 상에서 벌어지는 경우의 수는 런타임 모델로 다중 작업 처리를 해결하였기 때문에 필요성을 느끼지 못해 싱글쓰레드를 지원하는 것입니다.&lt;/p&gt;
&lt;p data-ke-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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동기적을 실행되는 복잡한 계산은 setImmediate(callback)을 사용하여, 각 작업을 chunk 하는 방식이 있고,&lt;/li&gt;
&lt;li&gt;fork를 사용한 멀티 프로세스 방식을 채용할 수도 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위 두 방식 보다 WebAPI에서는 Web Workers API를 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주 실행 스레드와 분리된 별도의 백그라운드 스레드에서 실행할 수 있는 방식을 통해 웹 애플리케이션에서 암호화, 압축/암축해제, 이미지조작, 컴퓨터비전(얼굴인식) 등의 수행을 도울 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Web_Workers_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/Web_Workers_API&lt;/a&gt;]&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ML 모델을 사용자들에게 서빙하는 방식에는 2가지 방식이 있다고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 최근에는 Large-Model이 큰 성능을 내고 있기 때문에 서버와의 통신을 통해서 결과값을 받아 보여주는 방식을 주로 사용하고 있지만, 점점 Client기기의 성능이 향상되는 만큼 경량화된 ML모델을 client에서 직접 띄워서 사용하는 방식도 사용될 가능성이 높아진다고 생각합니다.&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;그럴 때 더욱이 JavaScript의 런타임 모델은 고민해 볼 수 있는 좋은 내용인 것 같습니다.&lt;/p&gt;
&lt;p data-ke-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://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://chanyeong.com/blog/post/44&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://chanyeong.com/blog/post/44&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://yceffort.kr/2021/04/nodejs-multithreading-worker-threads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://yceffort.kr/2021/04/nodejs-multithreading-worker-threads&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://stackoverflow.com/questions/39879/why-doesnt-javascript-support-multithreading&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/39879/why-doesnt-javascript-support-multithreading&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming Language/JavaScript</category>
      <category>EventRoop</category>
      <category>JavaScript</category>
      <category>js</category>
      <category>Runtime</category>
      <category>singleThread</category>
      <category>런타임모델</category>
      <category>멀티쓰레드</category>
      <category>싱글쓰레드</category>
      <category>이벤트루프</category>
      <category>자바스크립트</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/89</guid>
      <comments>https://roothyo.tistory.com/89#entry89comment</comments>
      <pubDate>Wed, 13 Jul 2022 12:10:54 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript - Promise (프로미스)</title>
      <link>https://roothyo.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;비동기적으로 해야할 작업이 많아지면 코드는 자연스레 깊어지고 이는 콜백 지옥을 불러오며 이를 해결하기 위해서 프로미스를 사용한다고 언급한 바가 있습니다. 이번 포스팅은 프로미스에 대해 알아보도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다.기본적으로 promise는 함수에 콜백을 전달하는 대신에, 콜백을 첨부하는 방식의 객체입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 다음 중 하나의 상태를 가집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대기(Pending) : 이행하지도, 거부하지도 않은 초기 상태&lt;/li&gt;
&lt;li&gt;이행(fulfilled) : 연산이 성공적으로 완료됨.&lt;/li&gt;
&lt;li&gt;거부(rejected) : 연산이 실패함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대기 중인 프로미스는 값과 함께 이행할 수도, 어떤 이유로 인해 거부될 수도 있습니다. 이행이나 거부 될 때, 프로미스의 then 메서드에 의해 대기열(큐)에 추가된 처리기들이 호출됩니다.&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;801&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b95gfc/btrG3K9EqOy/dIaQse0wa2kQWwGz9IG4w1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b95gfc/btrG3K9EqOy/dIaQse0wa2kQWwGz9IG4w1/img.png&quot; data-alt=&quot;Promise 구동 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b95gfc/btrG3K9EqOy/dIaQse0wa2kQWwGz9IG4w1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb95gfc%2FbtrG3K9EqOy%2FdIaQse0wa2kQWwGz9IG4w1%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;801&quot; height=&quot;297&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Promise 구동 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 성공적으로 이행된 콜백 함수는 then을 통해, 실패해서 실행된 콜백함수는 catch를 통해서 error handling을 진행합니다.&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setTimeout은 특정 밀리초 동안 대기하고 시간이 지나면 실행하는 함수입니다. 각 2000ms, 1500ms, 1000ms 의 시간차를 두고 시간이 지나면, log를 남기는 코드를 작성하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657542181687&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function log(num){
    console.log(`${num} workers finished`);
}

setTimeout(log, 2000, 1)
setTimeout(log, 1500, 2)
setTimeout(log, 1000, 3)

// 3 workers finished
// 2 workers finished
// 1 workers finished&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000ms로 설정된 3번이 가장 먼저, 1500ms 인 2번이 다음, 2000ms인 1번이 마지막으로 출력된 것을 볼 수 있습니다.&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;기본적으로 웹은 서버에서 리소스를 가져오는 작업을 진행합니다. 사이트 상의 렌더링 되는 Text의 용량에 비해 Photo나 Video의 용량은 확연히 크기 때문에, Video나 Photo를 다 가져오기 전까지 화면이 그려지지 않는다면 사용자는 큰 불편함을 느낄 것입니다. 즉 이런 related to blocking 등의 이유들 때문에 웹 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;보통 2개 이상의 비동기 작업을 순차적으로 실행해야 하는 상황을 흔히 보게 됩니다. 그러나 비동기 함수의 수행 시간에 따라 어떤 함수가 먼저 끝날지를 모르게 되고, 기대와 *다른 값을 얻어 난처한 상황이 생깁니다.. 이를 해결하기 위해 콜백형태로 chaining을 하게 되고 결국 콜백 지옥에 빠지게 되는 것을 방지하기 위해 프로미스를 사용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;(* 주로 연산을 끝낸 변수의 값을 확인하려고 console.log를 찍을 때 연산 이전 값이 출력되는 경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 예로 자주 사용하는 프로미스 기반 HTTP 클라이언트인 Axios의 코드를 보도록 하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657540336180&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;'use strict';

import AxiosError from './AxiosError.js';

/**
 * Resolve or reject a Promise based on response status.
 *
 * @param {Function} resolve A function that resolves the promise.
 * @param {Function} reject A function that rejects the promise.
 * @param {object} response The response.
 *
 * @returns {object} The response.
 */
export default function settle(resolve, reject, response) {
  const validateStatus = response.config.validateStatus;
  if (!response.status || !validateStatus || validateStatus(response.status)) {
    resolve(response);
  } else {
    reject(new AxiosError(
      'Request failed with status code ' + response.status,
      [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4],
      response.config,
      response.request,
      response
    ));
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드는 response status에 따라 resolve와 reject 콜백을 반환하는 모습을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적인 프로미스 메소드에 대한 내용은 MDN API doc에서 확인할 수 있습니다.&lt;/p&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://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://elvanov.com/2597&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://elvanov.com/2597&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing&lt;/a&gt;]&lt;/p&gt;</description>
      <category>Programming Language/JavaScript</category>
      <category>JavaScript</category>
      <category>js</category>
      <category>promise</category>
      <category>비동기</category>
      <category>콜백지옥</category>
      <category>프로미스</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/88</guid>
      <comments>https://roothyo.tistory.com/88#entry88comment</comments>
      <pubDate>Mon, 11 Jul 2022 22:57:14 +0900</pubDate>
    </item>
    <item>
      <title>[FE] 브라우저 작동 원리</title>
      <link>https://roothyo.tistory.com/87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 아마 사람들이 가장 많이 사용하는 소프트웨어 중 하나이며,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글을 통해서 어떤 과정을 거쳐 웹 페이지가 화면에 보이게 되는지 알게 될 것입니다.&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;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kAWnV/btrGYz2txlS/qu2NI2PK7RejztJN30k1m1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kAWnV/btrGYz2txlS/qu2NI2PK7RejztJN30k1m1/img.png&quot; data-alt=&quot;브라우저의 주요 구성 요소&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kAWnV/btrGYz2txlS/qu2NI2PK7RejztJN30k1m1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkAWnV%2FbtrGYz2txlS%2Fqu2NI2PK7RejztJN30k1m1%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;417&quot; height=&quot;283&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;브라우저의 주요 구성 요소&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자 인터페이스&lt;br /&gt;: 주소 표시줄, 이전/다음버튼, 북마크 메뉴 등, 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분.&lt;/li&gt;
&lt;li&gt;브라우저 엔진 &lt;br /&gt;: 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어.&lt;/li&gt;
&lt;li&gt;렌더링 엔진 &lt;br /&gt;: 요청한 콘텐츠를 표시. HTML을 요청하면 HTML과 CSS를 파싱하여 화면에 그리는 엔진&lt;/li&gt;
&lt;li&gt;통신 &lt;br /&gt;: HTTP 요청과 같은 네트워크 호출에 사용됨. 플랫폼 독립적인 인터페이스로 각 플랫폼 하부에서 실행.&lt;/li&gt;
&lt;li&gt;UI 백엔드&lt;br /&gt;: 콤보 박스와 창 같은 기본적인 장치를 그림. OS 사용자 인터페이스 체계를 사용.&lt;/li&gt;
&lt;li&gt;자바스크립트 해석기&lt;br /&gt;: 자바스크립트 코드를 해석하고 실행.&lt;/li&gt;
&lt;li&gt;자료저장소&lt;br /&gt;: 쿠키를 저장하는 것과 같이 다양한 종류의 자원을 하드디스크에 저장할수 있는 자료 저장 계층.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;크롬은 대부분의 브라우저와 달리 각 탭마다 별도의 렌더링 엔진 인스턴스를 유지되어 독립된 프로세스로 처리됩니다. 그럼 주소창에 도메인을 입력하면 어떤 프로세스로 우리가 보는 웹 사이트를 보는 지 크게 2가지 방식으로 나누어서 알아보겠습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;서버와의 통신&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 통신을 통해 해당 웹 사이트 서버로 부터 정보를 가져오는 부분입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;619&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qvBuf/btrG1yPliXq/YKLGhnyxKt0onSjx3rYfp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qvBuf/btrG1yPliXq/YKLGhnyxKt0onSjx3rYfp0/img.png&quot; data-alt=&quot;브라우저로 웹 사이트에 접속할 때 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qvBuf/btrG1yPliXq/YKLGhnyxKt0onSjx3rYfp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqvBuf%2FbtrG1yPliXq%2FYKLGhnyxKt0onSjx3rYfp0%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;559&quot; height=&quot;422&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;619&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;1. 브라우저 주소창에 도메인을 입력합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 호스트 캐시를 조회하여 &lt;span&gt;사용자가 입력한 URL 주소중에서 도메인 이름(Domain Name)부분의&lt;/span&gt; IP주소를 확인합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 만약, 없다면 DNS의 Resolver(통신사 별 DNS 서버) 캐시에서 IP주소를 확인합니다. Resolver가 모르는 경우 루트 서버에 질의 하여 IP주소를 반환합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 받아온 IP 주소와 사용자가 입력한 URL 정보(param)로 HTTP 프로토콜을 생성하여 HTTP 요청 메시지를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 생성된 HTTP 요청 메시지는 TCP 프로토콜을 사용하여 인터넷을 거쳐 해당 IP 주소의 컴퓨터(웹 서버)로 전송합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 서버에 도착한 HTTP 요청 메시지의 URL&amp;nbsp; 정보에 해당하는 데이터(HTML, CSS, JS)를 서버에서 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 생성된 웹 페이지 데이터를 다시 HTTP 프로토콜을 사용하여 HTTP 응답 메시지 등의 Header와 함께 요청한 컴퓨터(PC)로 데이터를 전송합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. 도착한 HTTP 메시지를 브라우저가 해석하고 웹페이지를 사용자가 볼 수 있게 합니다.&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;렌더링 엔진&lt;/b&gt;의 역할은 서버로 요청해서 받은 내용을 가지고 브라우저 화면에 표시하는 일을 합니다. 사파리와 크롬은 Webkit 렌더링 엔진을 사용합니다. 렌더링 과정은 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B0xOs/btrG0Br0Gl1/2KcegIGrgw0thQL8a0eTX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B0xOs/btrG0Br0Gl1/2KcegIGrgw0thQL8a0eTX1/img.png&quot; data-alt=&quot;Webkit 동작 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B0xOs/btrG0Br0Gl1/2KcegIGrgw0thQL8a0eTX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB0xOs%2FbtrG0Br0Gl1%2F2KcegIGrgw0thQL8a0eTX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;625&quot; height=&quot;289&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Webkit 동작 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. HTML 파서를 통해서 HTML 마크업을 처리하고 DOM 트리를 빌드합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. CSS 파서를 통해서 CSSOM 트리를 빌드합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. DOM과 CSSOM을 결합하여 렌더링 트리를 형성합니다.&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;5. 개별 노드를 화면에 렌더링하여 사용자에게 시각화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* &lt;b&gt;DOM(Document Object Model)&lt;/b&gt;&lt;br /&gt;: 문서 객체 모델은 HTML 문서의 프로그래밍 interface로 프로그래밍 언어(JS, bs4 ...)가 DOM 구조에 접근 할 수 있는 방법을 제공하며, 문서 구조, 스타일, 내용 변경등을 도와준다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크적인 부분, 보안적인 부분 등 더 깊숙히 바라 볼 수 있는 부분들이 많기 때문에 오늘은 전체적인 그림만 그렸다고 할 수 있습니다. 특히 Front-End 개발을 진행할 경우 성능을 지속적으로 높이는 것이 목표시 되기 때문에, 전체적인 구조를 파악하는 것이 매우 중요하다고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-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://d2.naver.com/helloworld/59361&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://d2.naver.com/helloworld/59361&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조 : &lt;a href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/FrontEnd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/FrontEnd&lt;/a&gt;]&lt;/p&gt;</description>
      <category>서비스개발(Web, App)/Front-End</category>
      <category>FRONT-END</category>
      <category>렌더링엔진</category>
      <category>브라우저</category>
      <category>브라우저동작</category>
      <category>프론트엔드</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/87</guid>
      <comments>https://roothyo.tistory.com/87#entry87comment</comments>
      <pubDate>Mon, 11 Jul 2022 16:27:17 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] [1차] 캐시 - python3</title>
      <link>https://roothyo.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문제 설명&lt;/p&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;캐시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지도개발팀에서 근무하는 제이지는 지도에서 도시 이름을 검색하면 해당 도시와 관련된 맛집 게시물들을 데이터베이스에서 읽어 보여주는 서비스를 개발하고 있다.&lt;br /&gt;이 프로그램의 테스팅 업무를 담당하고 있는 어피치는 서비스를 오픈하기 전 각 로직에 대한 성능 측정을 수행하였는데, 제이지가 작성한 부분 중 데이터베이스에서 게시물을 가져오는 부분의 실행시간이 너무 오래 걸린다는 것을 알게 되었다.&lt;br /&gt;어피치는 제이지에게 해당 로직을 개선하라고 닦달하기 시작하였고, 제이지는 DB 캐시를 적용하여 성능 개선을 시도하고 있지만 캐시 크기를 얼마로 해야 효율적인지 몰라 난감한 상황이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어피치에게 시달리는 제이지를 도와, DB 캐시를 적용할 때 캐시 크기에 따른 실행시간 측정 프로그램을 작성하시오.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;입력 형식&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 크기(cacheSize)와 도시이름 배열(cities)을 입력받는다.&lt;/li&gt;
&lt;li&gt;cacheSize는 정수이며, 범위는 0 ≦&lt;span&gt;&amp;nbsp;&lt;/span&gt;cacheSize&lt;span&gt;&amp;nbsp;&lt;/span&gt;≦ 30 이다.&lt;/li&gt;
&lt;li&gt;cities는 도시 이름으로 이뤄진 문자열 배열로, 최대 도시 수는 100,000개이다.&lt;/li&gt;
&lt;li&gt;각 도시 이름은 공백, 숫자, 특수문자 등이 없는 영문자로 구성되며, 대소문자 구분을 하지 않는다. 도시 이름은 최대 20자로 이루어져 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;출력 형식&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력된 도시이름 배열을 순서대로 처리할 때, &quot;총 실행시간&quot;을 출력한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조건&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 교체 알고리즘은&lt;span&gt;&amp;nbsp;&lt;/span&gt;LRU(Least Recently Used)를 사용한다.&lt;/li&gt;
&lt;li&gt;cache hit일 경우 실행시간은&lt;span&gt;&amp;nbsp;&lt;/span&gt;1이다.&lt;/li&gt;
&lt;li&gt;cache miss일 경우 실행시간은&lt;span&gt;&amp;nbsp;&lt;/span&gt;5이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;입출력 예제&lt;/h3&gt;
&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;캐시크기(cacheSize)&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;도시이름(cities)&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;실행시간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;[&quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;NewYork&quot;, &quot;LA&quot;, &quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;NewYork&quot;, &quot;LA&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;[&quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;[&quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;NewYork&quot;, &quot;LA&quot;, &quot;SanFrancisco&quot;, &quot;Seoul&quot;, &quot;Rome&quot;, &quot;Paris&quot;, &quot;Jeju&quot;, &quot;NewYork&quot;, &quot;Rome&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;[&quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;NewYork&quot;, &quot;LA&quot;, &quot;SanFrancisco&quot;, &quot;Seoul&quot;, &quot;Rome&quot;, &quot;Paris&quot;, &quot;Jeju&quot;, &quot;NewYork&quot;, &quot;Rome&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;[&quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;NewYork&quot;, &quot;newyork&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.814%;&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;width: 75.9302%;&quot;&gt;[&quot;Jeju&quot;, &quot;Pangyo&quot;, &quot;Seoul&quot;, &quot;NewYork&quot;, &quot;LA&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 8.13953%;&quot;&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;- level2 이다보니 구현문제에 가까웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 캐시가 0인 경우를 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 캐시를 dict로 구현했는데, queue 형식으로 구현하면 추가적인 연산을 줄일 수 있다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1657521945732&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(cacheSize, cities):
    answer = 0
    cache = {}
    for idx, city in enumerate(cities):
        city = city.lower()
        if city in cache:
            cache[city] = idx
            answer += 1
        else: # Not cache
            if len(cache) &amp;lt; cacheSize:
                cache[city] = idx
            elif cacheSize &amp;gt; 0:
                target = ''
                minValue = float('inf')
                for k,v in cache.items():
                    if minValue &amp;gt; v:
                        target = k
                        minValue = v
                # Change Caching
                del cache[target]
                cache[city] = idx
            answer += 5
        # print(answer, cache)


    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>ComputerScience/코딩테스트</category>
      <category>Python3</category>
      <category>캐시</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>Roothyo</author>
      <guid isPermaLink="true">https://roothyo.tistory.com/86</guid>
      <comments>https://roothyo.tistory.com/86#entry86comment</comments>
      <pubDate>Mon, 11 Jul 2022 15:46:34 +0900</pubDate>
    </item>
  </channel>
</rss>