Congratulations!

[Valid RSS] This is a valid RSS feed.

Recommendations

This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: http://blog.dramancompany.com/feed/

  1. <?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
  2. xmlns:content="http://purl.org/rss/1.0/modules/content/"
  3. xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  4. xmlns:dc="http://purl.org/dc/elements/1.1/"
  5. xmlns:atom="http://www.w3.org/2005/Atom"
  6. xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  7. xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  8. xmlns:georss="http://www.georss.org/georss"
  9. xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
  10. >
  11.  
  12. <channel>
  13. <title>DRAMA&amp;COMPANY</title>
  14. <atom:link href="https://blog.dramancompany.com/feed/" rel="self" type="application/rss+xml" />
  15. <link>https://blog.dramancompany.com/</link>
  16. <description>DReam And MAke it happen</description>
  17. <lastBuildDate>Wed, 06 Mar 2024 08:16:43 +0000</lastBuildDate>
  18. <language>ko-KR</language>
  19. <sy:updatePeriod>
  20. hourly </sy:updatePeriod>
  21. <sy:updateFrequency>
  22. 1 </sy:updateFrequency>
  23.  
  24. <image>
  25. <url>https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/cropped-remember-appIcon.png?fit=32%2C32&#038;ssl=1</url>
  26. <title>DRAMA&amp;COMPANY</title>
  27. <link>https://blog.dramancompany.com/</link>
  28. <width>32</width>
  29. <height>32</height>
  30. </image>
  31. <site xmlns="com-wordpress:feed-additions:1">167555839</site> <item>
  32. <title>AWS re:Invent 2023 참관기</title>
  33. <link>https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/</link>
  34. <comments>https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/#respond</comments>
  35. <dc:creator><![CDATA[민규 박]]></dc:creator>
  36. <pubDate>Mon, 04 Mar 2024 02:15:16 +0000</pubDate>
  37. <category><![CDATA[Tech]]></category>
  38. <category><![CDATA[AWS]]></category>
  39. <category><![CDATA[reinvent]]></category>
  40. <category><![CDATA[컨퍼런스]]></category>
  41. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3642</guid>
  42.  
  43. <description><![CDATA[<p>안녕하세요? PSE(Platform Server Engineering) 파트 DevOps 이정민, 빅데이터센터 AI Lab ML engineer 박민규입니다. 이렇게 2명은 2023 AWS re:Invent를 다녀왔는데요, event 참관기를 들려 드리려 합니다! 목차는 다음과 같습니다. 1. AWS re:Invent 소개 2. AWS re:Invent를 준비하며(Tip 포함)&#160; 3. 현장 소개 4. 인상적이었던 세션 소개 1. AWS re:Invent 소개 AWS는 다양한 크기의 이벤트들을 개최하지만, 그중에서도 주목할 만한 [&#8230;]</p>
  44. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/">AWS re:Invent 2023 참관기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  45. ]]></description>
  46. <content:encoded><![CDATA[
  47. <p>안녕하세요? PSE(Platform Server Engineering) 파트 DevOps 이정민, 빅데이터센터 AI Lab ML engineer 박민규입니다. 이렇게 2명은 2023 AWS re:Invent를 다녀왔는데요, event 참관기를 들려 드리려 합니다!</p>
  48.  
  49.  
  50.  
  51. <p>목차는 다음과 같습니다.</p>
  52.  
  53.  
  54.  
  55. <p>1. AWS re:Invent 소개</p>
  56.  
  57.  
  58.  
  59. <p>2. AWS re:Invent를 준비하며(Tip 포함)&nbsp;</p>
  60.  
  61.  
  62.  
  63. <p>3. 현장 소개</p>
  64.  
  65.  
  66.  
  67. <p>4. 인상적이었던 세션 소개</p>
  68.  
  69.  
  70.  
  71. <p class="has-large-font-size"></p>
  72.  
  73.  
  74.  
  75. <h2><strong>1. AWS re:Invent 소개</strong></h2>
  76.  
  77.  
  78.  
  79. <p>AWS는 다양한 크기의 이벤트들을 개최하지만, 그중에서도 주목할 만한 메이저 이벤트는 세 가지입니다. 이 중 re:Inforce는 클라우드 보안, 컴플라이언스, 신원 및 프라이버시에 초점을 맞춘 행사로, 규모는 크지 않지만 매년 그 중요성이 커지고 있습니다. 반면, re:Mars는 Machine Learning (ML), Automation, Robotics, 및 Space (MARS) 분야에 중점을 두고 있어 기술의 최전선을 엿볼 수 있는 장입니다. 그러나 이 모든 것을 아우르는 가장 크고 포괄적인 이벤트는 바로 re:Invent입니다.</p>
  80.  
  81.  
  82.  
  83. <p>re:Invent는 AWS가 제공하는 모든 솔루션에 대해 다루며, 그 규모와 다양성에서 독보적입니다. 일반적으로 미국 네바다 주 라스베가스에서 열리는 이 이벤트는, 그 크기만큼이나 화려하고 방대합니다. re:Inforce와 같은 작은 이벤트들이 해마다 장소를 옮기는 것과 달리, re:Invent는 라스베가스의 메인 호텔들의 세미나룸을 전용으로 사용할 정도로 대규모입니다. 특히, 이번 2023년 re:Invent는 AI/ML에 큰 비중을 두었습니다. 다양한 세션들 중에서도 Amazon Bedrock에 관한 내용이 주목을 받았습니다.</p>
  84.  
  85.  
  86.  
  87. <p class="has-large-font-size"></p>
  88.  
  89.  
  90.  
  91. <h2><strong>2. AWS re:Invent를 준비하며(Tip 포함)</strong></h2>
  92.  
  93.  
  94.  
  95. <p>저희 드라마앤컴퍼니는 MSP 메가존클라우드와 파트너십을 맺고 있고, 메가존클라우드와 함께 이번 2023 AWS re:Invent를 참석하게 됐습니다. 메가존클라우드에서는 드라마앤컴퍼니 담당 매니저를 배정하여 비행기 예약, 호텔 예약 등 현지에서 필요한 부분들을 지원해주었습니다. 다만 event에서 들을 세션을 예약하는 것은 개인이 해야 하기 때문에 관심있는 세션을 놓치지 않고 예약하는게 중요합니다. re:Invent를 제대로 즐기기 위해서 세션 예약하는 방법과 Tip을 소개합니다.</p>
  96.  
  97.  
  98.  
  99. <h4>1) 세션 예약 날짜와 시간 잘 check하기</h4>
  100.  
  101.  
  102.  
  103. <p>세션 예약 일시에 대한 정보가 공식 홈페이지에 잘 안 보일 수 있으니 한국 AWS 공식 사이트나 커뮤니티를 잘 확인하고 회원가입 할 때 사용한 이메일도 잘 확인하여 정확한 예약 일시를 확인합니다. 예약이 시작되면 실시간으로 인기있는 세션들은 금방 예약이 완료되니 우선순위에 따라 개인의 전략대로 예약하는 것을 권장드립니다! re:Invent는 미국에서 열리기 때문에 예약 일시도 보통 미국 시간에 맞춰서 정해집니다. 그래서 한국 시간으로는 새벽에 예약해야 한다는 것..! 잊지 말아 주세요.</p>
  104.  
  105.  
  106.  
  107. <h4>2) 동선에 따른 세션 즐겨찾기</h4>
  108.  
  109.  
  110.  
  111. <p>공식 홈페이지에서 로그인하고 세션 목록을 즐겨찾기 해놓으면 예약할 때 바로 내가 원하는 세션을 골라 예약할 수 있습니다. 그런데 라스 베가스 strip(도시 중심부에 위치한, 세계적으로 유명한 호텔, 카지노, 레스토랑, 쇼핑몰, 엔터테인먼트 장소가 밀집된 지역)에서 세션이 열리는 호텔들이 멀리 떨어진 경우도 있고 호텔도 워낙 커서 세션장을 옮겨 다니는 데도 여유가 필요합니다. AWS에서는 참석자들의 편의를 위해 호텔에서 호텔 간의 셔틀 버스를 제공해줍니다. 그래서 하루 안에 너무 많은 호텔을 이동하는 것은 비효율적이고 1개에서 2개 정도 호텔을 골라 세션을 예약하는 것이 좋습니다. (아래 Figure 1을 보면 베니션, 시저스포럼은 가깝지만 만달레이베이와는 거리가 꽤 됩니다!)</p>
  112.  
  113.  
  114.  
  115. <p class="has-text-align-center"><img data-attachment-id="3644" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/reinvent-map-2023-png/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?fit=1200%2C584&amp;ssl=1" data-orig-size="1200,584" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="reinvent-map-2023.png" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?fit=300%2C146&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?fit=1024%2C498&amp;ssl=1" loading="lazy" width="1200" height="584" class="wp-image-3644" style="width: 900px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?resize=1200%2C584&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?w=1200&amp;ssl=1 1200w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?resize=300%2C146&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?resize=1024%2C498&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?resize=768%2C374&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?resize=750%2C365&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/reinvent-map-2023.png.webp?resize=1140%2C555&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  116.  
  117.  
  118.  
  119. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 1. AWS re:Invent Campus Map</mark></p>
  120.  
  121.  
  122.  
  123. <h4>3) 티켓 구매 후 내 사진 등록하기</h4>
  124.  
  125.  
  126.  
  127. <p>온라인으로 티켓을 구매한 뒤에 자신의 사진을 등록할 수 있습니다. 이 사진은 현장에서 수령받는 뱃지에 이미지로 들어가게 됩니다. 아래는 현장에서 수령한 뱃지를 찍은 사진인데요, 저(민규)는 사전에 사진을 등록하는 것을 깜빡해 현장에서 급하게 사진을 찍었습니다. 사람들의 뱃지를 보면 다들 멋진 사진을 미리 등록했던데 저는 그러지 못해 아쉬웠습니다.</p>
  128.  
  129.  
  130.  
  131. <p class="has-text-align-center"><img data-attachment-id="3647" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_6603/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?fit=706%2C1099&amp;ssl=1" data-orig-size="706,1099" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="IMG_6603" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?fit=193%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?fit=658%2C1024&amp;ssl=1" loading="lazy" width="706" height="1099" class="wp-image-3647" style="width: 180px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?resize=706%2C1099&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?w=706&amp;ssl=1 706w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?resize=193%2C300&amp;ssl=1 193w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6603.png?resize=658%2C1024&amp;ssl=1 658w" sizes="(max-width: 706px) 100vw, 706px" data-recalc-dims="1" /></p>
  132.  
  133.  
  134.  
  135. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#666666" class="has-inline-color">Figure 2. 수령한 뱃지</mark></p>
  136.  
  137.  
  138.  
  139. <p class="has-large-font-size"></p>
  140.  
  141.  
  142.  
  143. <h2><strong>3. 현장 소개</strong></h2>
  144.  
  145.  
  146.  
  147. <h4>1) 현장 분위기</h4>
  148.  
  149.  
  150.  
  151. <p>IT 관련 event 중 거의 가장 큰 event인 만큼 현장의 규모는 압도적으로 느껴졌고, 그 규모를 모두 감당하기 위해 이뤄지는 시스템은 상당히 효율적이었습니다. 처음 등록 할 때 뱃지와 후드를 수령하게 되는데 매우 빠르게 진행되다보니 사람들이 많아도 기다리는 시간이 길지 않았습니다. 등록한 사람들 한정으로 제공하는 무료 식사와 간식을 먹는 데도 수월했고 호텔 간 이동도 매우 편리했습니다. 여러번 event를 진행하면서 쌓인 노하우가 느껴졌던 것 같습니다. Event 기간 동안 느낀 불편함은 전혀 없었기에 세션에 집중할 수 있었고 event를 오로지 즐길 수 있었습니다.</p>
  152.  
  153.  
  154.  
  155. <p>AWS re:Invent 기간동안 strip에는 re:Invent에 참여하는 엔지니어들로 가득 차있었습니다. 지나가는 대부분의 사람들이 뱃지를 목에 걸고 있었고 특히 참여자들에게 굿즈로 나눠주는 기모 후드집업을 다들 입고 다녀서 약간의 소속감(?)을 느낄 수도 있었습니다. 물론 화려함으로 유명한 도시 답게 패셔너블한 사람들도 종종 보였지만 전세계의 너드들이 도시를 가득 채우고 있다보니 신기하기도 하고 재밌기도 했습니다. 그렇게 도시에 같은 목적을 가진 사람들이 많이 있다보니 좋았던 점도 있었는데요, 처음 도시를 적응 할 때 도움이 많이 되었습니다. 뱃지를 수령하러 갈 때나 호텔 간의 이동을 할 때 길이 복잡해서 찾기가 어려운 상황이 발생 했는데 후드티를 입은 사람들이 가는 길을 따라가다보면 자연스럽게 제가 원하는 장소에 도착해있기도 했습니다! 저희가 묵었던 호텔은 시저스팰리스라는 호텔이었는데요, 숙소에서 세션장이 모여있는 베니션 호텔이나 시저스포럼은 거리가 가까워서 걸어 다녔습니다. 그런데 가는 길이 어렵다 보니 조금 헤매기도 했습니다. 가는 길이 여러 방법이 있어 가장 짧게 걸리는 길을 미리 파악해 놓는 것도 도움이 되니 현장에 일찍 도착하셨다면 미리 투어를 해보시는 것을 추천해 드립니다!</p>
  156.  
  157.  
  158.  
  159. <p class="has-text-align-center"><img data-attachment-id="3649" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_6637/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?fit=840%2C1120&amp;ssl=1" data-orig-size="840,1120" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="IMG_6637" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?fit=225%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?fit=768%2C1024&amp;ssl=1" loading="lazy" width="840" height="1120" class="wp-image-3649" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?resize=840%2C1120&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?w=840&amp;ssl=1 840w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?resize=225%2C300&amp;ssl=1 225w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?resize=768%2C1024&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6637.png?resize=750%2C1000&amp;ssl=1 750w" sizes="(max-width: 840px) 100vw, 840px" data-recalc-dims="1" />          <img data-attachment-id="3650" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_6640/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?fit=840%2C1120&amp;ssl=1" data-orig-size="840,1120" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="IMG_6640" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?fit=225%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?fit=768%2C1024&amp;ssl=1" loading="lazy" width="840" height="1120" class="wp-image-3650" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?resize=840%2C1120&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?w=840&amp;ssl=1 840w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?resize=225%2C300&amp;ssl=1 225w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?resize=768%2C1024&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6640.png?resize=750%2C1000&amp;ssl=1 750w" sizes="(max-width: 840px) 100vw, 840px" data-recalc-dims="1" /></p>
  160.  
  161.  
  162.  
  163. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#666666" class="has-inline-color">Figure 3. 시저스 포럼 내부 통로 / Figure 4. 세션장 내부 분위기</mark></p>
  164.  
  165.  
  166.  
  167. <h4>2) 세션장 소개</h4>
  168.  
  169.  
  170.  
  171. <p>세션을 시작하기 전에 AWS 행사장에 도착하면, 예약자와 미예약자로 나누어진 두 줄에 서게 됩니다. 인기 있는 세션의 경우, 일찍 줄을 서지 않으면 서 있을 공간조차 없어 세션에 참여하지 못할 수 있습니다. 실제로 정말 인기 있는 세션에는 사람들이 30분에서 1시간 전부터 줄을 서기 시작합니다. 만약 세션에 들어가지 못한다면, 화면으로 세션을 시청할 수 있는 공간이 마련되어 있으며, 각 의자에 비치된 무선 헤드셋을 통해 스피커의 목소리를 더욱 선명하게 들을 수 있습니다. 그럼에도 현장에서 직접 듣는 경험은 또 다른 매력을 가지고 있어, 이 분위기를 직접 느껴보는 것이 좋습니다. 대부분의 세션은 나중에 유튜브를 통해 들을 수 있지만, 영상 녹화를 하지 않는 세션도 있어, 현장에서 녹음하거나 슬라이드를 사진으로 찍어 기록하는 것도 좋은 방법이 될 수 있습니다. 세션은 호텔마다 주로 다루는 주제가 있어서 관심 있는 주제가 주로 오픈된 호텔에서 집중적으로 세션을 듣는 것도 좋을 것 같습니다. 한 호텔에서 여러 세션을 연이어 듣다 보면 휴식이 필요한데, 로비마다 과자나 커피 등의 다과가 제공되니 이런 휴식공간을 잘 즐기며 체력을 보충하는 것도 좋은 방법입니다!</p>
  172.  
  173.  
  174.  
  175. <p>만약 호텔이 아직 익숙하지 않아 세션장을 찾기 어려울 때는 &#8216;Ask me&#8217;라고 쓰인 노란 티셔츠를 입은 사람을 찾아 질문하면 친절하게 안내해줍니다. 여담으로 노란 티셔츠를 입은 분들은 대부분 라스베이거스 거주민으로 이러한 행사가 있을 때 단기 알바로 지원해 행사를 돕는다고 합니다. 세션의 종류에 따라 분위기가 다양한데, Q&amp;A 시간을 많이 주는 활발한 세션도 있고, 거의 강연식으로 정보만 전달하고 끝나는 세션도 있습니다. 너무 듣기만 하는 세션으로 일정을 구성하면 지루할 수 있으니, 다양한 형식의 세션을 경험해 보는 것을 추천해 드립니다!</p>
  176.  
  177.  
  178.  
  179. <p class="has-text-align-center"><img data-attachment-id="3648" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_6588/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?fit=840%2C1120&amp;ssl=1" data-orig-size="840,1120" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="IMG_6588" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?fit=225%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?fit=768%2C1024&amp;ssl=1" loading="lazy" width="840" height="1120" class="wp-image-3648" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?resize=840%2C1120&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?w=840&amp;ssl=1 840w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?resize=225%2C300&amp;ssl=1 225w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?resize=768%2C1024&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6588.png?resize=750%2C1000&amp;ssl=1 750w" sizes="(max-width: 840px) 100vw, 840px" data-recalc-dims="1" /></p>
  180.  
  181.  
  182.  
  183. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 5. Ask me!를 입고있는 안내원</mark></p>
  184.  
  185.  
  186.  
  187. <h4>3) Expo 소개</h4>
  188.  
  189.  
  190.  
  191. <p>Expo는 AWS의 파트너 및 기술 솔루션 제공 업체들을 직접 만나보고 체험 할 수 있는 공간입니다. 업체들은 부스를 만들어 자신들의 서비스와 솔루션을 전시합니다. 업체마다 부스 규모가 상이한데 어떤 부스에서는 자신들만의 프리젠테이션 타임을 갖고 작은 세션을 진행하기도 합니다. 저는(민규) 특히 AI와 관련된 솔루션에 관심이 있어 LightningAI나 DATASTAX와 같은 업체에서 제공하는 솔루션에 대해 이야기를 나누며 의미있는 시간을 가졌습니다. 원래 Lightning은 AI를 개발할 때 사용하는 라이브러리인데 해당 팀에서 AI 데이터, 학습, 배포 등을 편리하게 하나의 솔루션으로 관리할 수 있도록 LightningAI라는 앱을 만들었습니다. 또한, 드라마앤컴퍼니는 vector search에도 관심이 많은데 DATASTAX가 관련한 솔루션을 제공하고 있어 소개받은 기능들이 흥미롭다고 느꼈습니다.</p>
  192.  
  193.  
  194.  
  195. <p>또 눈길을 끌었던 것은 DeepRacer의 자율주행 모델 competition이었는데요, 세계 각국의 AI engineer들이 각자가 만든 강화학습 모델을 대회에 등록하고 자신의 알고리즘으로 장난감 자동차를 자율주행하도록 했습니다. 누가 더 빠르게 경기장을 도는지 rap time을 재고 순위가 실시간으로 변경되는 것을 보니 알고리즘을 만든 engineer들이 멋지다는 생각이 들었습니다.</p>
  196.  
  197.  
  198.  
  199. <p>부스를 돌아다니다 보면 각 업체에서 굿즈(Swag)를 주는데요, 보통 티셔츠를 주는 곳이 많고 스티커, 모자 등을 얻을 수 있습니다. Expo는 보통 월~목까지 진행되지만, 수요일이나 목요일 즈음에 가게 되면 제공하는 굿즈들이 품절되어 못 받을 수 있으니 굿즈에 진심이라면 일찍 Expo를 돌아보시는 것을 추천해 드립니다! 굿즈를 받을 때는 목에 걸고 있는 뱃지를 찍게 되는데요, 뱃지를 찍으면 나의 이메일 주소가 해당 업체에 등록되고 업체는 event 이후 등록한 이메일에 cold mail을 보내게 됩니다. 굿즈를 많이 수집하면 그만큼 나의 이메일 주소가 많이 노출되는 것이니 cold mail을 걱정한다면 처음 event 등록 할 때 sub 이메일 주소를 적는 편이 더 나을 것 같습니다.</p>
  200.  
  201.  
  202.  
  203. <p class="has-text-align-center"><img data-attachment-id="3654" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_6732/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?fit=840%2C1120&amp;ssl=1" data-orig-size="840,1120" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="IMG_6732" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?fit=225%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?fit=768%2C1024&amp;ssl=1" loading="lazy" width="840" height="1120" class="wp-image-3654" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?resize=840%2C1120&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?w=840&amp;ssl=1 840w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?resize=225%2C300&amp;ssl=1 225w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?resize=768%2C1024&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6732.png?resize=750%2C1000&amp;ssl=1 750w" sizes="(max-width: 840px) 100vw, 840px" data-recalc-dims="1" /></p>
  204.  
  205.  
  206.  
  207. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 6. Expo 내부 분위기</mark></p>
  208.  
  209.  
  210.  
  211. <h4>4) Networking</h4>
  212.  
  213.  
  214.  
  215. <p>AWS re:Invent는 다양한 나라, 다양한 기업에의 engineer들이 모이는 곳이니 networking도 정말 중요한 부분입니다. Networking을 통해 나누는 대화에서 좋은 insight를 얻을 수도 있고 맺어 놓은 좋은 관계가 나중에 나의 업무에 도움이 될 수도 있기 때문입니다. 첫날에는 AWS 한국인의 밤이 열렸는데요. 많은 한국인이 넓은 bar에 모여 라이브 음악을 들으면서 음식을 즐기고 테이블에 앉아 networking을 했습니다. 서로 명함을 주고받고. 서로가 하는 일을 소개했고, 회사 분위기나 업무에 대한 고충 같은 이야기를 나눴습니다. 또 저희 드라마앤컴퍼니는 벤더사인 메가존클라우드에서 만든 자리에 참석하여 다양한 Engineer들을 만나 흥미로운 대화들을 나눴습니다. 낮에는 세션을 듣고 밤에는 이런 networking 자리에 참여하다 보니 체력관리도 중요하다는 것을 깨달았습니다.</p>
  216.  
  217.  
  218.  
  219. <p>진행했던 세션 중에 한국어 세션들도 몇개가 있어 참석해봤는데 거기서도 좋은 networking 기회들이 있었습니다. 세션이 마무리되고 speaker를 찾아가 몇가지 질문을 하면서 명함을 주고받고 친분을 쌓을 수 있었습니다. 심지어 비행기에서 만난 인연들도 있었는데요, 돌아가는 첫 비행에서는 AWS에서 일하는 Account Manager와 대화를 나누며 링크드인을 교환하고 두 번째 비행에서는 AI 관련 논문을 읽고 있던 soft engineer와 networking을 했습니다. 먼저 다가가는 것이 어려운 것도 있고 언어의 장벽도 있지만 이렇게 주어진 기회들을 놓치지 않고 networking에 적극적인 자세로 임한다면 돌아봤을 때 후회가 없을 것 같다는 생각이 들었습니다.</p>
  220.  
  221.  
  222.  
  223. <p class="has-large-font-size"></p>
  224.  
  225.  
  226.  
  227. <h2><strong>4. 인상적이었던 세션 소개</strong></h2>
  228.  
  229.  
  230.  
  231. <h4>정민</h4>
  232.  
  233.  
  234.  
  235. <p>마이그레이션</p>
  236.  
  237.  
  238.  
  239. <p>저는 다양한 주제의 세션들에 참가하였는데요. 첫 번째로는 얼마 전 마무리된 AWS 리전 마이그레이션 작업을 대비하기 위해 Multi-region 아키텍처 구성, Mass Migration과 관련된 세션을 여럿 참석했습니다. 다소 뻔한 얘기일 수 있지만 Multi-region 아키텍처를 잘 구성하기 위해서는 ‘모든 인프라 리소스를 코드화’하고, ‘리전 간 인프라 배포에 소요되는 시간(bake time)’에 여유를 두어야 한다는 것을 강조하였는데요. 저희도 리전 마이그레이션을 위해 모든 인프라 리소스를 Terraform으로 관리하고 있었고, 덕분에 지난 1월 무사히 마이그레이션 작업을 마무리할 수 있었습니다. (Figure 7)</p>
  240.  
  241.  
  242.  
  243. <p class="has-text-align-center"><img data-attachment-id="3659" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/838698b3-a5ab-426e-a25e-a2180bc7bf7d/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?fit=1190%2C893&amp;ssl=1" data-orig-size="1190,893" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="838698B3-A5AB-426E-A25E-A2180BC7BF7D" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?fit=300%2C225&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?fit=1024%2C768&amp;ssl=1" loading="lazy" width="1190" height="893" class="wp-image-3659" style="width: 600px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?resize=1190%2C893&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?w=1190&amp;ssl=1 1190w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?resize=300%2C225&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?resize=1024%2C768&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?resize=768%2C576&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?resize=750%2C563&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/838698B3-A5AB-426E-A25E-A2180BC7BF7D.png?resize=1140%2C855&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  244.  
  245.  
  246.  
  247. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 7</mark></p>
  248.  
  249.  
  250.  
  251. <p>기조연설</p>
  252.  
  253.  
  254.  
  255. <p>re:Invent에서 또 빼놓을 수 없는 것이 바로 기조연설인데요. 매일 아침 진행되는 기조연설은 AWS의 CEO, CTO를 비롯한 임원들이 등장하여 현재 AWS가 집중하고 있는 서비스와 신기능에 대한 Summary를 제공합니다. 올해에도 여러가지 흥미로운 주제가 있었지만, 특히나 LLM과 GenAI 등 AI 기술에 대한 내용이 돋보였는데요. 행사 둘째날 기조연설에서 공개된 Amazon Q는 AWS가 제공하는 GenAI 서비스로, 공개 당일에 프리뷰 버전이 AWS 콘솔에서 사용 가능하도록 바로 배포가 되었습니다. 저도 세션을 듣던 중간에 AWS 콘솔에 임베딩된 Amazon Q와 몇 마디 대화를 나눠보았는데요. 대부분의 질문에 잘 답변하는 모습을 확인할 수 있었습니다. (Figure 8)</p>
  256.  
  257.  
  258.  
  259. <p class="has-text-align-center"><img data-attachment-id="3660" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/image-2-6/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?fit=1222%2C1526&amp;ssl=1" data-orig-size="1222,1526" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image (2)" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?fit=240%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?fit=820%2C1024&amp;ssl=1" loading="lazy" width="1222" height="1526" class="wp-image-3660" style="width: 700px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?resize=1222%2C1526&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?w=1222&amp;ssl=1 1222w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?resize=240%2C300&amp;ssl=1 240w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?resize=820%2C1024&amp;ssl=1 820w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?resize=768%2C959&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?resize=750%2C937&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/image-2.png?resize=1140%2C1424&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  260.  
  261.  
  262.  
  263. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 8</mark>. Amazon Q로 네트워크 라우팅 이슈를 디버깅하는 모습(출처: <a href="https://aws.amazon.com/ko/blogs/networking-and-content-delivery/introducing-amazon-q-support-for-network-troubleshooting/" target="_blank" rel="noreferrer noopener">https://aws.amazon.com/ko/blogs/networking-and-content-delivery/introducing-amazon-q-support-for-network-troubleshooting/</a>)</p>
  264.  
  265.  
  266.  
  267. <p>Amazon Q</p>
  268.  
  269.  
  270.  
  271. <p>Amazon Q는 나, 혹은 우리 조직의 Private repository나 Wiki 등의 데이터와 연동하여 Personalized된 답변을 받아볼 수도 있고, Amazon Connect와 연동하여 고객센터의 상담이 더 빠르고 정확하게 진행될 수 있도록 연동하는 기능도 제공하고 있습니다. (OpenAI의 ChatGPT또한 비슷한 기능들을 모두 지원하고 있어요. 아쉬운 점은 ChatGPT는 한국어를 지원하지만 Amazon Q는 아직 한국어를 지원하지 않습니다.) 저희 팀에서도 올해 내부 로그 분석과 장애대응 Runbook에 GenAI를 통합하는 테스트를 진행할 계획을 가지고 있는데요. 더 편리한 연동을 위해 Amazon Q의 한국어 지원이 빠르게 릴리즈되기를 희망하고 있습니다.</p>
  272.  
  273.  
  274.  
  275. <p>마지막으로 리멤버가 엄청난 사용자 데이터와 뛰어난 AI 모델을 가지고 있는 만큼, 저도 자연스럽게 데이터 파이프라인과 ML 워크로드에 대한 관심을 많이 가지게 되었는데요. 이번 re:Invent를 기점으로 AWS Glue, Redshift와 같은 관리형 서비스에서 Apache Iceberg를 지원한다고 하여, Iceberg 기반의 분석 플랫폼을 구성하는 세션에 참석해보았습니다. 기존 Hadoop 시스템의 HDFS와 다르게 설계부터 S3와 같은 Object Storage를 고려하였다는 점이 인상적이었고, 이러한 장점들을 배경으로 Netflix가 Hive에서 Iceberg 생태계로 전환하는 과정 역시 흥미로운 주제였습니다. (Figure 9)</p>
  276.  
  277.  
  278.  
  279. <p class="has-text-align-center"><img data-attachment-id="3658" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/6fc7f5c7-b6ea-45a3-b8d5-b8539762a663_1_105_c/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?fit=1024%2C769&amp;ssl=1" data-orig-size="1024,769" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?fit=300%2C225&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?fit=1024%2C769&amp;ssl=1" loading="lazy" width="1024" height="769" class="wp-image-3658" style="width: 570px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?resize=1024%2C769&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?w=1024&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?resize=300%2C225&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?resize=768%2C577&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/6FC7F5C7-B6EA-45A3-B8D5-B8539762A663_1_105_c.jpeg?resize=750%2C563&amp;ssl=1 750w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  280.  
  281.  
  282.  
  283. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 9</mark></p>
  284.  
  285.  
  286.  
  287. <p>Express One Zone</p>
  288.  
  289.  
  290.  
  291. <p>또, 새롭게 출시된 S3 Storage Class인 Express One Zone에 관련된 세션에 참석했는데요. Express One Zone Class는 S3 Standard Class와 다르게, 데이터를 1개 AZ에만 저장하는 대신, 훨씬 빠른 Access 속도를 제공하는 스토리지 클래스입니다. 데이터를 1개 AZ에만 저장하기 때문에 같은 AZ에 위치한 컴퓨팅 리소스에서 접근하는 경우 데이터 액세스 속도가 빠르고, GetObject 비용이 Standard class 대비 50%까지 저렴하다는 장점을 가지고 있습니다. 세션에서는 HA가 필요하지 않고, 작은 사이즈의 분석용 데이터(ex. parquet와 같은)를 잠시 올려두는 용도의 사용을 예시로 들어주었는데요. 최근 발표된 S3 MountPoint 기능과 결합하여 어플리케이션 레이어에서도 Temporary한 파일을 로딩하는 용도로 운영하기에 괜찮을 것 같다는 아이디어를 얻었습니다. (Figure 10)</p>
  292.  
  293.  
  294.  
  295. <p class="has-text-align-center"><img data-attachment-id="3661" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_0782/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?fit=2560%2C1920&amp;ssl=1" data-orig-size="2560,1920" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="IMG_0782" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?fit=300%2C225&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?fit=1024%2C768&amp;ssl=1" loading="lazy" width="2560" height="1920" class="wp-image-3661" style="width: 570px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=2560%2C1920&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?w=2560&amp;ssl=1 2560w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=300%2C225&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=1024%2C768&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=768%2C576&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=1536%2C1152&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=2048%2C1536&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=750%2C563&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_0782-scaled.jpg?resize=1140%2C855&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  296.  
  297.  
  298.  
  299. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 10</mark></p>
  300.  
  301.  
  302.  
  303. <p class="has-x-large-font-size"></p>
  304.  
  305.  
  306.  
  307. <h4>민규</h4>
  308.  
  309.  
  310.  
  311. <p>저는 정민님처럼 여러 세션을 소개하기 보다 한 세션을 집중적으로 소개할까 합니다. 소개 할 세션 제목은 ‘What’s new in Amazon OpenSearch Service’ 입니다. 저는(민규) ML Engineer로서 AI와 관련된 여러 세션을 들었는데 저희 팀에서 사용하고 있는 OpenSearch에 대한 신기능이 있다고 하여 기대감을 가지고 참석했습니다. 해당 세션을 듣기 전까지 AI 관련 세션을 들었지만 AWS Bedrock에 대한 설명이 많고 중복되어 흥미가 떨어진 상태였습니다. 하지만 해당 세션을 듣고 다시 즐겁게 event를 참여할 수 있었고, 들었던 내용을 동료들과 공유하면 어떨까 하고 생각했습니다. 해당 세션은 AWS OpenSearch에서 새롭게 추가된 feature를 소개하는 세션이었습니다. Speaker는 두 명으로 파트를 나눠서 발표했습니다. 세션 도중 질의응답이 서로 오가는 시간도 있어 더욱 풍부하게 세션을 즐길 수 있었습니다.</p>
  312.  
  313.  
  314.  
  315. <p class="has-text-align-center"><img data-attachment-id="3672" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/img_6815-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?fit=1920%2C2560&amp;ssl=1" data-orig-size="1920,2560" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;1.5&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;iPhone 13 Pro&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;1701360048&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;5.6999998092633&quot;,&quot;iso&quot;:&quot;640&quot;,&quot;shutter_speed&quot;:&quot;0.028571428571429&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;1&quot;}" data-image-title="IMG_6815" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?fit=225%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?fit=768%2C1024&amp;ssl=1" loading="lazy" width="1920" height="2560" class="wp-image-3672" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=1920%2C2560&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?w=1920&amp;ssl=1 1920w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=225%2C300&amp;ssl=1 225w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=768%2C1024&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=1152%2C1536&amp;ssl=1 1152w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=1536%2C2048&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=750%2C1000&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/IMG_6815-scaled.jpeg?resize=1140%2C1520&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  316.  
  317.  
  318.  
  319. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 11. What&#8217;s new in OpenSearch 세션 현장</mark></p>
  320.  
  321.  
  322.  
  323. <p>OpenSearch란?</p>
  324.  
  325.  
  326.  
  327. <p>OpenSearch에 대해서 간단히 설명하자면, 2021년 오픈 소스 프로젝트로 Elasticsearch의 기능을 더욱 확장한 업그레이드 버전입니다. Elasticsearch는 검색 서비스에서 주로 사용하는 솔루션으로 빠른 검색을 가능하게 해줍니다. 구체적으로 Lucene의 역인덱스(Inverted Index) 기술을 활용하는데요, 역인덱스란 문서를 찾을 때 단어마다 인덱스(단어가 가지는 고유한 번호)를 지정해놓고 단어로 검색했을 때 해당 단어를 가진 문서를 빠르게 찾는 방법을 의미합니다. 역인덱스는 단어 기반으로만 문서를 찾기에 문서와 문서의 의미를 반영하지 못한다는 단점을 갖습니다. 이 단점을 극복한 방법이 바로 semantic search입니다. Semantic search는 검색 쿼리와 찾고자 하는 문서의 의미를 임베딩 벡터로 표현하고 벡터의 유사도 점수를 구해 점수가 높은 문서를 상위에 큐레이션 해주는 방법입니다. 보통 모든 문서 임베딩 벡터를 OpenSearch DB에 미리 저장하고, 검색 요청이 들어왔을 때 검색 쿼리 임베딩 벡터를 OpenSearch에 던져서 저장된 문서 임베딩 벡터와 계산하여 문서 목록을 뽑아주게 됩니다. 저희도 해당 기술을 활용해 공고(쿼리)에 적합한 프로필(문서)을 기업에 추천해주거나, 반대로 프로필(쿼리)에 적합한 공고(문서)를 추천해주고 있습니다. 이번 세션에서는 OpenSearch에서 제공하는 Data Engineering에 관한 부분과 Semantic Search(Search Engineering)에 관한 부분을 주로 다뤘습니다.</p>
  328.  
  329.  
  330.  
  331. <p>Data Engineering</p>
  332.  
  333.  
  334.  
  335. <p>새롭게 소개되는 Amazon OpenSearch Ingestion은 Amazon Web Services(AWS)에서 제공하는 특별한 기능으로, 사용자가 실시간 로그, 지표, 추적 데이터 등을 Amazon OpenSearch Service 도메인과 서버리스 컬렉션에 쉽게 제공할 수 있게 해주는 완전 관리형 서버리스 데이터 수집기입니다. 이 기능을 사용하면 Logstash나 Jaeger와 같은 타사 솔루션에 의존하지 않고도 데이터를 수집하고 처리할 수 있습니다. Amazon OpenSearch Ingestion은 오픈소스 DataPrepper를 사용하여 구현되며, 이는 데이터를 추적, 변환, 병합, 샘플링하는 등의 다양한 데이터 파이프라인 작업을 가능하게 합니다. 특히 DynamoDB와의 zero-ETL(integration) 통합을 통해, 사용자는 DynamoDB 테이블을 데이터 수집을 위해 직접 사용할 수 있게 되어, 데이터 처리 과정이 대폭 간소화됩니다. DynamoDB는 AWS가 제공하는 완전 관리형 NoSQL 데이터베이스 서비스로, 이를 통한 데이터 수집은 AWS Management Console에서 쉽게 설정할 수 있으며, 이는 데이터 관리와 분석 작업을 더욱 효율적이고 간편하게 만들어 줍니다. Amazon OpenSearch Ingestion을 사용함으로써, 기술적인 복잡성을 크게 줄이면서도 강력한 데이터 분석 및 검색 기능을 활용할 수 있게 됩니다.</p>
  336.  
  337.  
  338.  
  339. <p>그리고 OpenSearch에 대한 Migration Assistant에 대한 기능도 소개되었는데요, 자체 관리형 ES(Elasticsearch)나 OS(OpenSearch) 클러스터를 Amazon OpenSearch Service의 관리형 클러스터나 serverless collection으로 migration하는 데 도와주는 솔루션입니다. 기존 데이터 및 실시간 데이터를 자동으로 migration 할 수 있게 해줍니다. 특히 기존 클러스터에 방해되지 않게 migration 가능하기에 migration을 생각하고 있다면 좋은 feature가 될 것 같습니다.</p>
  340.  
  341.  
  342.  
  343. <p>Search Engineering</p>
  344.  
  345.  
  346.  
  347. <p>앞서 설명한 것처럼 OpenSearch에서는 역인덱스를 사용하는 Text Search를 넘어서 Semantic Search 기능을 제공합니다. 각 검색 쿼리와 문서는 텍스트 뿐만 아니라 이미지, 영상, 음성 등의 데이터로 이뤄질 수도 있는데요, 핵심은 semantic(의미론적) 유사성을 찾아주는 것입니다. 임베딩 벡터는 이 semantic 정보를 가지고 있습니다. 그래서 벡터 공간이라고 불리는 수학적 공간에 아래의 그림과 같이 표현 될 수 있는거죠!</p>
  348.  
  349.  
  350.  
  351. <p>그래서 Semantic Search는 Vector Search라고도 표현 할 수 있는데요, 아래의 그림(Figure?)을 보면 Vector Search의 workflow를 확인 할 수 있습니다. Raw data는 chuck(문서)로 구분되고 각 chuck는 머신러닝 모델에 의해 숫자로 이루어진 n차원의 임베딩 벡터로 표현됩니다. OpenSearch vector database에 저장되고 각 문서는 index를 갖게 됩니다. 마지막으로 검색이나 분석에 필요할 때마다 불러와 사용됩니다. AI chatbot(Figure?)으로 예를 들어보겠습니다. 사용자가 chatbot에 어떤 question을 던졌을 때 이 question text는 LLM의 모델에 입력되고 임베딩 벡터를 얻게 됩니다. 여기서 Semantic Search를 수행하여 가장 유사한 임베딩 벡터(OpenSearch에 이미 저장된)를 찾아 정렬합니다. 해당 결과를 다시 LLM에 입력하여 Question에 알맞게 다시 자연어로 출력합니다. Semantic Search 기능은 이러한 chatbot 말고도 비슷한 데이터를 빠르게 찾는 기능이 필요한 서비스라면 적용이 가능합니다.</p>
  352.  
  353.  
  354.  
  355. <p class="has-text-align-center"><img data-attachment-id="3662" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b71-3/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?fit=1862%2C944&amp;ssl=1" data-orig-size="1862,944" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?fit=300%2C152&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?fit=1024%2C519&amp;ssl=1" loading="lazy" width="1862" height="944" class="wp-image-3662" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=1862%2C944&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?w=1862&amp;ssl=1 1862w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=300%2C152&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=1024%2C519&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=768%2C389&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=1536%2C779&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=750%2C380&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림1.png?resize=1140%2C578&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  356.  
  357.  
  358.  
  359. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 12</mark>. Vector Search workflow</p>
  360.  
  361.  
  362.  
  363. <p class="has-text-align-center"><img data-attachment-id="3663" data-permalink="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b72-3/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?fit=1804%2C936&amp;ssl=1" data-orig-size="1804,936" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?fit=300%2C156&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?fit=1024%2C531&amp;ssl=1" loading="lazy" width="1804" height="936" class="wp-image-3663" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=1804%2C936&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?w=1804&amp;ssl=1 1804w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=300%2C156&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=1024%2C531&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=768%2C398&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=1536%2C797&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=750%2C389&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2024/03/그림2.png?resize=1140%2C591&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  364.  
  365.  
  366.  
  367. <p class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#656565" class="has-inline-color">Figure 13</mark>. Chatbot workflow</p>
  368.  
  369.  
  370.  
  371. <p>추가적인 Search Engineering의 새로운 features</p>
  372.  
  373.  
  374.  
  375. <p>또한, OpenSearch는 Semantic Search와 같은 방법과 기존의 전통적인 방법(역인덱스와 같은)을 혼합해서 사용할 수 있는 Hybrid Search, AWS에서 제공하는 pre-trained 모델을 fine tuning 할 수 있는 기능, Semantic Search보다 정확도는 떨어지지만 속도와 메모리에서 이점이 있는 Sparse vector retrieval 기능, 이미지와 텍스트를 혼합해서 사용 할 수 있는 Multimodal search 기능을 새롭게 제공합니다. 특히 AWS 2023 야심작인 Bedrock은 OpenSearch와 함께 손쉽게 사용 가능합니다. Bedrock은 여러개의 Gen AI모델(Anthropic, Meta 등에서 출시한 모델들)을 지원하고 fine tuning하여 새로운 나만의 모델을 만들 수도 있습니다. S3에 나만의 데이터를 저장하고 RAG 또한 활용 할 수 있습니다. 기존에 AI 모델을 사용할 때는 외부에서 모델을 가져와 AWS 시스템에 적용하는 일이 굉장히 복잡하고 쉽지 않았다면 AWS Bedrock을 사용하면 AWS 내에서 아주 편리하고 빠르게 사용할 수 있게 되었습니다.</p>
  376.  
  377.  
  378.  
  379. <p>그 외 features</p>
  380.  
  381.  
  382.  
  383. <p>OpenSearch는 Jaeger(분산 추적 시스템으로, 마이크로서비스 아키텍처에서 소프트웨어의 성능 문제를 진단하고 모니터링하는 데 사용)를 통해서 로그를 추적하고 메트릭을 추출하는 자동화 기능을 추가하는 등 완전한 시각화 기능을 구축했습니다. 그리고 OpenSearch Assistant도 소개했는데요, 오픈소스로 제공하고 있고 아직은 베타 버전이지만 자연어를 통해서 다룰 수 있고, toolkit을 customizing 할 수 있고, AI 모델을 연결 할 수 있습니다. 그 외 Security Analytics 기능도 제공합니다. Security log 응답 시간을 줄이고 잠재적 위험을 빠르게 인지하며 이해관계자들에게 알림을 보냄으로써 빨리 대응 할 수 있도록 합니다. 마지막으로 Zero-ETL integration을 제공합니다. 오픈서치 서비스 간에 전환할 필요 없이 Amazon S3에 저장된 운영 로그를 쿼리할 수 있는 새로운 방법인데요. 대용량의 로그 데이터를 저장하고 관리하는 경우 s3에 데이터를 저장하고 오픈서치에서 인덱싱하고 분석할 수 있습니다. 인터렉티브하게 분석할 수 있고, zero etl을 통해 중복을 최소화하는 쿼리가 가능하고, 가속화 기능을 통해서 쿼리 퍼포먼스를 증가시킬 수 있습니다. 가속화 기능에는 인덱스 건너뛰기, 인덱스 포함 등이 있습니다. 복잡한 설정이나 추가 개발 없이 시각화가 가능합니다.</p>
  384.  
  385.  
  386.  
  387. <p class="has-large-font-size"></p>
  388.  
  389.  
  390.  
  391. <h3>마무리하며</h3>
  392.  
  393.  
  394.  
  395. <p>저희는 이번 행사를 통해 얻은 지식과 경험을 바탕으로 앞으로의 업무에 새로운 아이디어와 솔루션을 적극적으로 도입하고, 개선해 나갈 계획입니다. 또한, 이번 행사에서 만난 다양한 분야의 전문가들과의 네트워킹을 통해 얻은 인사이트와 연결고리를 통해 지속적인 교류와 협력의 기회를 모색할 것입니다. AWS re:Invent는 단순한 기술 컨퍼런스를 넘어서, 최신 클라우드 기술의 동향을 파악하고, 글로벌 네트워크를 확장하며, 미래의 혁신을 모색하는 중요한 장이었습니다. 이번 참관기가 AWS re:Invent에 관심 있는 분들에게 유용한 정보와 인사이트를 제공했기를 바라며, 앞으로도 계속해서 새로운 기술과 트렌드에 대해 공유하고 소통하는 기회를 가지길 희망합니다. 지금까지 긴 글을 읽어주셔서 감사합니다!</p>
  396. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/">AWS re:Invent 2023 참관기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  397. ]]></content:encoded>
  398. <wfw:commentRss>https://blog.dramancompany.com/2024/03/aws-reinvent-2023-%ec%b0%b8%ea%b4%80%ea%b8%b0/feed/</wfw:commentRss>
  399. <slash:comments>0</slash:comments>
  400. <post-id xmlns="com-wordpress:feed-additions:1">3642</post-id> </item>
  401. <item>
  402. <title>리멤버에서 UT(사용자 테스트)는 어떻게 진행하나요?</title>
  403. <link>https://blog.dramancompany.com/2023/09/how-to-ux-research/</link>
  404. <comments>https://blog.dramancompany.com/2023/09/how-to-ux-research/#comments</comments>
  405. <dc:creator><![CDATA[희경 김]]></dc:creator>
  406. <pubDate>Thu, 14 Sep 2023 09:20:12 +0000</pubDate>
  407. <category><![CDATA[Design]]></category>
  408. <category><![CDATA[remember]]></category>
  409. <category><![CDATA[research]]></category>
  410. <category><![CDATA[ux]]></category>
  411. <category><![CDATA[uxdesign]]></category>
  412. <category><![CDATA[ux디자인]]></category>
  413. <category><![CDATA[ux리서치]]></category>
  414. <category><![CDATA[디자인팀]]></category>
  415. <category><![CDATA[리멤버]]></category>
  416. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3594</guid>
  417.  
  418. <description><![CDATA[<p>안녕하세요. 리멤버 프로덕트 디자이너 김희경입니다. 명함관리 서비스로 시작해 구인구직 서비스와 직장인 커뮤니티 서비스, 데일리 뉴스 콘텐츠까지 직장인을 위한 다양한 서비스를 리멤버에서 제공해왔는데요. 이 모든 서비스를 한 화면에서 경험할 수 있는 새로운 화면을 신설하기에 앞서 사용성 테스트(Usability Test)를 진행했었어요. 새로운 피쳐가 배포되기 이전에 사용성 테스트를 진행하며 경험한 UT 설계와 모더레이팅 과정에서 느낀 인사이트를 공유드릴게요. UT(사용성 테스트)는 [&#8230;]</p>
  419. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2023/09/how-to-ux-research/">리멤버에서 UT(사용자 테스트)는 어떻게 진행하나요?</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  420. ]]></description>
  421. <content:encoded><![CDATA[ <div data-elementor-type="wp-post" data-elementor-id="3594" class="elementor elementor-3594">
  422. <div class="elementor-inner">
  423. <div class="elementor-section-wrap">
  424. <section class="elementor-section elementor-top-section elementor-element elementor-element-d3a21b1 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="d3a21b1" data-element_type="section">
  425. <div class="elementor-container elementor-column-gap-default">
  426. <div class="elementor-row">
  427. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-42ac4f8" data-id="42ac4f8" data-element_type="column">
  428. <div class="elementor-column-wrap elementor-element-populated">
  429. <div class="elementor-widget-wrap">
  430. <div class="elementor-element elementor-element-78681f9 elementor-widget elementor-widget-image" data-id="78681f9" data-element_type="widget" data-widget_type="image.default">
  431. <div class="elementor-widget-container">
  432. <div class="elementor-image">
  433. <img width="1920" height="1080" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?fit=1920%2C1080&amp;ssl=1" class="attachment-full size-full" alt="" loading="lazy" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?w=1920&amp;ssl=1 1920w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?resize=1024%2C576&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?resize=768%2C432&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?resize=1536%2C864&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?resize=750%2C422&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?resize=1140%2C641&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-attachment-id="3602" data-permalink="https://blog.dramancompany.com/2023/09/how-to-ux-research/how-to-ux/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?fit=1920%2C1080&amp;ssl=1" data-orig-size="1920,1080" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="How-to-ux" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/How-to-ux.png?fit=1024%2C576&amp;ssl=1" /> </div>
  434. </div>
  435. </div>
  436. </div>
  437. </div>
  438. </div>
  439. </div>
  440. </div>
  441. </section>
  442. <section class="elementor-section elementor-top-section elementor-element elementor-element-d7b2a70 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="d7b2a70" data-element_type="section">
  443. <div class="elementor-container elementor-column-gap-default">
  444. <div class="elementor-row">
  445. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-16b857e" data-id="16b857e" data-element_type="column">
  446. <div class="elementor-column-wrap elementor-element-populated">
  447. <div class="elementor-widget-wrap">
  448. <div class="elementor-element elementor-element-896b00a elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor" data-id="896b00a" data-element_type="widget" data-widget_type="text-editor.default">
  449. <div class="elementor-widget-container">
  450. <div class="elementor-text-editor elementor-clearfix">
  451. <p>안녕하세요. 리멤버 프로덕트 디자이너 김희경입니다.</p><p>명함관리 서비스로 시작해 구인구직 서비스와 직장인 커뮤니티 서비스, 데일리 뉴스 콘텐츠까지 직장인을 위한 다양한 서비스를 리멤버에서 제공해왔는데요. 이 모든 서비스를 한 화면에서 경험할 수 있는 새로운 화면을 신설하기에 앞서 사용성 테스트(Usability Test)를 진행했었어요. 새로운 피쳐가 배포되기 이전에 사용성 테스트를 진행하며 경험한 UT 설계와 모더레이팅 과정에서 느낀 인사이트를 공유드릴게요.</p> </div>
  452. </div>
  453. </div>
  454. </div>
  455. </div>
  456. </div>
  457. </div>
  458. </div>
  459. </section>
  460. <section class="elementor-section elementor-top-section elementor-element elementor-element-48d1768 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="48d1768" data-element_type="section">
  461. <div class="elementor-container elementor-column-gap-default">
  462. <div class="elementor-row">
  463. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6e34805" data-id="6e34805" data-element_type="column">
  464. <div class="elementor-column-wrap elementor-element-populated">
  465. <div class="elementor-widget-wrap">
  466. <div class="elementor-element elementor-element-1d3b1be elementor-widget elementor-widget-heading" data-id="1d3b1be" data-element_type="widget" data-widget_type="heading.default">
  467. <div class="elementor-widget-container">
  468. <h2 class="elementor-heading-title elementor-size-default">UT(사용성 테스트)는 언제 진행하나요?</h2> </div>
  469. </div>
  470. </div>
  471. </div>
  472. </div>
  473. </div>
  474. </div>
  475. </section>
  476. <section class="elementor-section elementor-top-section elementor-element elementor-element-cc3b6c1 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="cc3b6c1" data-element_type="section">
  477. <div class="elementor-container elementor-column-gap-default">
  478. <div class="elementor-row">
  479. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c35e035" data-id="c35e035" data-element_type="column">
  480. <div class="elementor-column-wrap elementor-element-populated">
  481. <div class="elementor-widget-wrap">
  482. <div class="elementor-element elementor-element-b80455a elementor-widget elementor-widget-text-editor" data-id="b80455a" data-element_type="widget" data-widget_type="text-editor.default">
  483. <div class="elementor-widget-container">
  484. <div class="elementor-text-editor elementor-clearfix">
  485. <p>UT 즉 사용성 테스트는 신규 기능을 기획하는 단계 또는 신규 기능을 론칭하기 전 실제 리멤버 사용자에게 보여드리면서 우리 생각대로 사용하시는지, 문제점은 없는지 검증하기 위해 진행합니다.</p><p>특히 이번처럼 첫 화면을 신규로 만드는 경우는, 기존 대비 사용자가 불편하게 느끼시는 부분은 없는지 사전에 확인하는 것이 매우 중요했어요.</p> </div>
  486. </div>
  487. </div>
  488. </div>
  489. </div>
  490. </div>
  491. </div>
  492. </div>
  493. </section>
  494. <section class="elementor-section elementor-top-section elementor-element elementor-element-980d96d elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="980d96d" data-element_type="section">
  495. <div class="elementor-container elementor-column-gap-default">
  496. <div class="elementor-row">
  497. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-60f8e97" data-id="60f8e97" data-element_type="column">
  498. <div class="elementor-column-wrap elementor-element-populated">
  499. <div class="elementor-widget-wrap">
  500. <div class="elementor-element elementor-element-b907605 elementor-widget elementor-widget-heading" data-id="b907605" data-element_type="widget" data-widget_type="heading.default">
  501. <div class="elementor-widget-container">
  502. <h2 class="elementor-heading-title elementor-size-default">UT 설계</h2> </div>
  503. </div>
  504. </div>
  505. </div>
  506. </div>
  507. </div>
  508. </div>
  509. </section>
  510. <section class="elementor-section elementor-top-section elementor-element elementor-element-4d5cfc4 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="4d5cfc4" data-element_type="section">
  511. <div class="elementor-container elementor-column-gap-default">
  512. <div class="elementor-row">
  513. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-282a6c2" data-id="282a6c2" data-element_type="column">
  514. <div class="elementor-column-wrap elementor-element-populated">
  515. <div class="elementor-widget-wrap">
  516. <div class="elementor-element elementor-element-e45fd7e elementor-widget elementor-widget-text-editor" data-id="e45fd7e" data-element_type="widget" data-widget_type="text-editor.default">
  517. <div class="elementor-widget-container">
  518. <div class="elementor-text-editor elementor-clearfix">
  519. <p>UT는 ‘설계가 80%다.’라는 생각이 들 정도로 설계 과정이 매우 중요하다고 생각해요.</p><p>UT 대상자는 누구를 어떤 과정으로 모집할 것인지, 인터뷰는 온라인으로 할 것인지, 오프라인으로 할 것인지, 인터뷰 관찰자는 어떤 방식으로 참여할지 등등 준비할 것이 생각보다 많았습니다.</p><p>그럼 어떤 순서와 과정을 거쳐 UT 설계를 했었는지 알려드릴게요.</p> </div>
  520. </div>
  521. </div>
  522. </div>
  523. </div>
  524. </div>
  525. </div>
  526. </div>
  527. </section>
  528. <section class="elementor-section elementor-top-section elementor-element elementor-element-2294ef1 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="2294ef1" data-element_type="section">
  529. <div class="elementor-container elementor-column-gap-default">
  530. <div class="elementor-row">
  531. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9d16221" data-id="9d16221" data-element_type="column">
  532. <div class="elementor-column-wrap elementor-element-populated">
  533. <div class="elementor-widget-wrap">
  534. <div class="elementor-element elementor-element-4e5daf6 elementor-widget elementor-widget-heading" data-id="4e5daf6" data-element_type="widget" data-widget_type="heading.default">
  535. <div class="elementor-widget-container">
  536. <h3 class="elementor-heading-title elementor-size-default">01. 인터뷰 대상자 선정</h3> </div>
  537. </div>
  538. </div>
  539. </div>
  540. </div>
  541. </div>
  542. </div>
  543. </section>
  544. <section class="elementor-section elementor-top-section elementor-element elementor-element-ad89b67 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="ad89b67" data-element_type="section">
  545. <div class="elementor-container elementor-column-gap-default">
  546. <div class="elementor-row">
  547. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-be419c7" data-id="be419c7" data-element_type="column">
  548. <div class="elementor-column-wrap elementor-element-populated">
  549. <div class="elementor-widget-wrap">
  550. <div class="elementor-element elementor-element-f003826 elementor-widget elementor-widget-text-editor" data-id="f003826" data-element_type="widget" data-widget_type="text-editor.default">
  551. <div class="elementor-widget-container">
  552. <div class="elementor-text-editor elementor-clearfix">
  553. <p>사용자 행위에 영향을 미치는 조건을 리스트업 합니다.</p><ul><li>우리 서비스를 사용한 기간이 얼마나 되었는지</li><li>그중 어떤 서비스를 중점적으로 사용하는지</li><li>우리 서비스를 방문하는 주기는 어떻게 되는지</li><li>IT 기기 조작이 익숙한 사람인지</li></ul><p>조건에 따라 사용자군을 나누기도 하고 하나의 사용자군을 대상으로 인터뷰를 진행할 수 있습니다.</p><p>이번 인터뷰에서는 사용자 행위에 따라 군을 나누어, 총 4개의 사용자군을 대상으로 인터뷰를 진행했어요.</p> </div>
  554. </div>
  555. </div>
  556. </div>
  557. </div>
  558. </div>
  559. </div>
  560. </div>
  561. </section>
  562. <section class="elementor-section elementor-top-section elementor-element elementor-element-a5dd014 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="a5dd014" data-element_type="section">
  563. <div class="elementor-container elementor-column-gap-default">
  564. <div class="elementor-row">
  565. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4ee3d90" data-id="4ee3d90" data-element_type="column">
  566. <div class="elementor-column-wrap elementor-element-populated">
  567. <div class="elementor-widget-wrap">
  568. <div class="elementor-element elementor-element-2a949ba elementor-widget elementor-widget-heading" data-id="2a949ba" data-element_type="widget" data-widget_type="heading.default">
  569. <div class="elementor-widget-container">
  570. <h3 class="elementor-heading-title elementor-size-default">02. 인터뷰 대상 리크루팅</h3> </div>
  571. </div>
  572. </div>
  573. </div>
  574. </div>
  575. </div>
  576. </div>
  577. </section>
  578. <section class="elementor-section elementor-top-section elementor-element elementor-element-d21f029 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="d21f029" data-element_type="section">
  579. <div class="elementor-container elementor-column-gap-default">
  580. <div class="elementor-row">
  581. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b01749e" data-id="b01749e" data-element_type="column">
  582. <div class="elementor-column-wrap elementor-element-populated">
  583. <div class="elementor-widget-wrap">
  584. <div class="elementor-element elementor-element-fe4260f elementor-widget elementor-widget-text-editor" data-id="fe4260f" data-element_type="widget" data-widget_type="text-editor.default">
  585. <div class="elementor-widget-container">
  586. <div class="elementor-text-editor elementor-clearfix">
  587. <p>우리가 선정한 대상자들에게 인터뷰 정보를 안내하고 모집합니다.</p> </div>
  588. </div>
  589. </div>
  590. </div>
  591. </div>
  592. </div>
  593. </div>
  594. </div>
  595. </section>
  596. <section class="elementor-section elementor-top-section elementor-element elementor-element-0c198a9 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="0c198a9" data-element_type="section">
  597. <div class="elementor-container elementor-column-gap-default">
  598. <div class="elementor-row">
  599. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-316a1d2" data-id="316a1d2" data-element_type="column">
  600. <div class="elementor-column-wrap elementor-element-populated">
  601. <div class="elementor-widget-wrap">
  602. <div class="elementor-element elementor-element-1ec61ee elementor-widget elementor-widget-image" data-id="1ec61ee" data-element_type="widget" data-widget_type="image.default">
  603. <div class="elementor-widget-container">
  604. <div class="elementor-image">
  605. <figure class="wp-caption">
  606. <img width="1920" height="1080" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?fit=1920%2C1080&amp;ssl=1" class="attachment-full size-full" alt="" loading="lazy" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?w=1920&amp;ssl=1 1920w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?resize=1024%2C576&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?resize=768%2C432&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?resize=1536%2C864&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?resize=750%2C422&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?resize=1140%2C641&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-attachment-id="3606" data-permalink="https://blog.dramancompany.com/2023/09/how-to-ux-research/%e1%84%85%e1%85%b5%e1%84%8f%e1%85%b3%e1%84%85%e1%85%ae%e1%84%90%e1%85%b5%e1%86%bc/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?fit=1920%2C1080&amp;ssl=1" data-orig-size="1920,1080" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="리크루팅" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/리크루팅.png?fit=1024%2C576&amp;ssl=1" /> <figcaption class="widget-image-caption wp-caption-text">Tally를 활용해서 인터뷰 대상자에게 사용성 테스트 요청을 진행</figcaption>
  607. </figure>
  608. </div>
  609. </div>
  610. </div>
  611. </div>
  612. </div>
  613. </div>
  614. </div>
  615. </div>
  616. </section>
  617. <section class="elementor-section elementor-top-section elementor-element elementor-element-368cafb elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="368cafb" data-element_type="section">
  618. <div class="elementor-container elementor-column-gap-default">
  619. <div class="elementor-row">
  620. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5bdedf8" data-id="5bdedf8" data-element_type="column">
  621. <div class="elementor-column-wrap elementor-element-populated">
  622. <div class="elementor-widget-wrap">
  623. <div class="elementor-element elementor-element-12d5c56 elementor-widget elementor-widget-text-editor" data-id="12d5c56" data-element_type="widget" data-widget_type="text-editor.default">
  624. <div class="elementor-widget-container">
  625. <div class="elementor-text-editor elementor-clearfix">
  626. <ul><li>인터뷰 환경 안내 : 온라인인지 오프라인인지</li><li>일정 스케줄링 : 가능한 날짜와 시간을 모두 받은 뒤 스케줄 조정 후 안내</li><li>인터뷰 동의 항목 안내 및 동의 받기</li><li>인터뷰 사례금 안내</li></ul><p>인터뷰 모집에 응답을 주신 분들 중에서 직무나 추가 조건 및 다양성을 고려하여 인터뷰 대상자를 선정했습니다.</p> </div>
  627. </div>
  628. </div>
  629. </div>
  630. </div>
  631. </div>
  632. </div>
  633. </div>
  634. </section>
  635. <section class="elementor-section elementor-top-section elementor-element elementor-element-e435274 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="e435274" data-element_type="section">
  636. <div class="elementor-container elementor-column-gap-default">
  637. <div class="elementor-row">
  638. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7a7405b" data-id="7a7405b" data-element_type="column">
  639. <div class="elementor-column-wrap elementor-element-populated">
  640. <div class="elementor-widget-wrap">
  641. <div class="elementor-element elementor-element-bae66db elementor-widget elementor-widget-heading" data-id="bae66db" data-element_type="widget" data-widget_type="heading.default">
  642. <div class="elementor-widget-container">
  643. <h3 class="elementor-heading-title elementor-size-default">03. 역할 분담</h3> </div>
  644. </div>
  645. </div>
  646. </div>
  647. </div>
  648. </div>
  649. </div>
  650. </section>
  651. <section class="elementor-section elementor-top-section elementor-element elementor-element-82200a1 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="82200a1" data-element_type="section">
  652. <div class="elementor-container elementor-column-gap-default">
  653. <div class="elementor-row">
  654. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-301cfaf" data-id="301cfaf" data-element_type="column">
  655. <div class="elementor-column-wrap elementor-element-populated">
  656. <div class="elementor-widget-wrap">
  657. <div class="elementor-element elementor-element-9850083 elementor-widget elementor-widget-text-editor" data-id="9850083" data-element_type="widget" data-widget_type="text-editor.default">
  658. <div class="elementor-widget-container">
  659. <div class="elementor-text-editor elementor-clearfix">
  660. <p>이번 인터뷰는 신규 피처를 함께 기획했던 PO와 PD가 협업하여 진행했으며 아래의 역할을 나눠 UT를 준비했습니다.</p><ul><li>인터뷰 설계 및 모더레이팅</li><li>인터뷰 대상자 리쿠르팅 및 사례금 지급 담당자</li><li>서기, 관찰자</li></ul> </div>
  661. </div>
  662. </div>
  663. </div>
  664. </div>
  665. </div>
  666. </div>
  667. </div>
  668. </section>
  669. <section class="elementor-section elementor-top-section elementor-element elementor-element-da72949 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="da72949" data-element_type="section">
  670. <div class="elementor-container elementor-column-gap-default">
  671. <div class="elementor-row">
  672. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e342e22" data-id="e342e22" data-element_type="column">
  673. <div class="elementor-column-wrap elementor-element-populated">
  674. <div class="elementor-widget-wrap">
  675. <div class="elementor-element elementor-element-1e46744 elementor-widget elementor-widget-heading" data-id="1e46744" data-element_type="widget" data-widget_type="heading.default">
  676. <div class="elementor-widget-container">
  677. <h3 class="elementor-heading-title elementor-size-default">04. Task 작성</h3> </div>
  678. </div>
  679. </div>
  680. </div>
  681. </div>
  682. </div>
  683. </div>
  684. </section>
  685. <section class="elementor-section elementor-top-section elementor-element elementor-element-2409af8 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="2409af8" data-element_type="section">
  686. <div class="elementor-container elementor-column-gap-default">
  687. <div class="elementor-row">
  688. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-106ecc6" data-id="106ecc6" data-element_type="column">
  689. <div class="elementor-column-wrap elementor-element-populated">
  690. <div class="elementor-widget-wrap">
  691. <div class="elementor-element elementor-element-563a8b4 elementor-widget elementor-widget-image" data-id="563a8b4" data-element_type="widget" data-widget_type="image.default">
  692. <div class="elementor-widget-container">
  693. <div class="elementor-image">
  694. <figure class="wp-caption">
  695. <img width="1920" height="1080" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?fit=1920%2C1080&amp;ssl=1" class="attachment-full size-full" alt="" loading="lazy" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?w=1920&amp;ssl=1 1920w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?resize=1024%2C576&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?resize=768%2C432&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?resize=1536%2C864&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?resize=750%2C422&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?resize=1140%2C641&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-attachment-id="3605" data-permalink="https://blog.dramancompany.com/2023/09/how-to-ux-research/task/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?fit=1920%2C1080&amp;ssl=1" data-orig-size="1920,1080" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Task" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/Task.png?fit=1024%2C576&amp;ssl=1" /> <figcaption class="widget-image-caption wp-caption-text">사용자 인터뷰 진행에 사용되었던 Task 초안</figcaption>
  696. </figure>
  697. </div>
  698. </div>
  699. </div>
  700. </div>
  701. </div>
  702. </div>
  703. </div>
  704. </div>
  705. </section>
  706. <section class="elementor-section elementor-top-section elementor-element elementor-element-2d925d2 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="2d925d2" data-element_type="section">
  707. <div class="elementor-container elementor-column-gap-default">
  708. <div class="elementor-row">
  709. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0fae8b8" data-id="0fae8b8" data-element_type="column">
  710. <div class="elementor-column-wrap elementor-element-populated">
  711. <div class="elementor-widget-wrap">
  712. <div class="elementor-element elementor-element-894cb6d elementor-widget elementor-widget-text-editor" data-id="894cb6d" data-element_type="widget" data-widget_type="text-editor.default">
  713. <div class="elementor-widget-container">
  714. <div class="elementor-text-editor elementor-clearfix">
  715. <p>사용성 테스트를 통해 확인하고 싶은 내용을 중심으로 Task를 설계하고 성공 기준과 실패 기준을 정합니다.</p><p>신규 화면에서도 기존에 자주 사용하던 기능을 빠르게 찾을 수 있는지, 몰랐던 기능들을 어떻게 인지하고 사용하게 되는지 등 검증하고 싶은 내용을 플로우 별로 나누고 Task와 질문을 작성했습니다.</p><p>실제 인터뷰에서는 사용자군에 따라 Task의 순서를 변경하고 자연스러운 진행을 위해 사용자에게 몰입할 수 있는 시나리오와 함께 Task를 안내했습니다.</p> </div>
  716. </div>
  717. </div>
  718. </div>
  719. </div>
  720. </div>
  721. </div>
  722. </div>
  723. </section>
  724. <section class="elementor-section elementor-top-section elementor-element elementor-element-20a694e elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="20a694e" data-element_type="section">
  725. <div class="elementor-container elementor-column-gap-default">
  726. <div class="elementor-row">
  727. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-849010f" data-id="849010f" data-element_type="column">
  728. <div class="elementor-column-wrap elementor-element-populated">
  729. <div class="elementor-widget-wrap">
  730. <div class="elementor-element elementor-element-40a23a6 elementor-widget elementor-widget-heading" data-id="40a23a6" data-element_type="widget" data-widget_type="heading.default">
  731. <div class="elementor-widget-container">
  732. <h3 class="elementor-heading-title elementor-size-default">05. 프로토타입 준비</h3> </div>
  733. </div>
  734. </div>
  735. </div>
  736. </div>
  737. </div>
  738. </div>
  739. </section>
  740. <section class="elementor-section elementor-top-section elementor-element elementor-element-9343c00 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="9343c00" data-element_type="section">
  741. <div class="elementor-container elementor-column-gap-default">
  742. <div class="elementor-row">
  743. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f5a3192" data-id="f5a3192" data-element_type="column">
  744. <div class="elementor-column-wrap elementor-element-populated">
  745. <div class="elementor-widget-wrap">
  746. <div class="elementor-element elementor-element-d46c3bf elementor-widget elementor-widget-text-editor" data-id="d46c3bf" data-element_type="widget" data-widget_type="text-editor.default">
  747. <div class="elementor-widget-container">
  748. <div class="elementor-text-editor elementor-clearfix">
  749. <p>인터뷰에서 검증하고 싶은 가설을 확인할 수 있는 형태로 프로토타입을 준비합니다. 참고로 모든 기능이 동작하지 않아도 됩니다. 이번에는 인터뷰 대상 사용자군 별로 Task를 진행할 수 있는 프로토타입을 준비하고, Task 내용에 따라 프로토타입 접속 계정도 다르게 세팅하여 인터뷰 대상자에게 제공했습니다.</p> </div>
  750. </div>
  751. </div>
  752. </div>
  753. </div>
  754. </div>
  755. </div>
  756. </div>
  757. </section>
  758. <section class="elementor-section elementor-top-section elementor-element elementor-element-5186ebf elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="5186ebf" data-element_type="section">
  759. <div class="elementor-container elementor-column-gap-default">
  760. <div class="elementor-row">
  761. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-06a8860" data-id="06a8860" data-element_type="column">
  762. <div class="elementor-column-wrap elementor-element-populated">
  763. <div class="elementor-widget-wrap">
  764. <div class="elementor-element elementor-element-34145fb elementor-widget elementor-widget-heading" data-id="34145fb" data-element_type="widget" data-widget_type="heading.default">
  765. <div class="elementor-widget-container">
  766. <h3 class="elementor-heading-title elementor-size-default">06. 리허설 진행</h3> </div>
  767. </div>
  768. </div>
  769. </div>
  770. </div>
  771. </div>
  772. </div>
  773. </section>
  774. <section class="elementor-section elementor-top-section elementor-element elementor-element-6edf12b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="6edf12b" data-element_type="section">
  775. <div class="elementor-container elementor-column-gap-default">
  776. <div class="elementor-row">
  777. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6afafcb" data-id="6afafcb" data-element_type="column">
  778. <div class="elementor-column-wrap elementor-element-populated">
  779. <div class="elementor-widget-wrap">
  780. <div class="elementor-element elementor-element-ff888c8 elementor-widget elementor-widget-text-editor" data-id="ff888c8" data-element_type="widget" data-widget_type="text-editor.default">
  781. <div class="elementor-widget-container">
  782. <div class="elementor-text-editor elementor-clearfix">
  783. <p>실제 환경과 동일한 환경을 조성하고 사내에서 인터뷰 대상자를 1명을 선정하여 진행했습니다.</p><p>이때 관찰자로 디자인팀 동료들을 초대하여 인터뷰 과정을 지켜보고 이후 피드백을 받았습니다. 피드백을 바탕으로 인터뷰 대본 수정과 Task의 추가 질문들을 수정하여 실제 인터뷰를 진행하게 되었습니다.</p><p>실제 인터뷰를 진행하기 전 리허설 인터뷰는 필수로 진행하는 것을 추천해요. 예상하지 못한 현장에서의 변수들을 확인할 수 있고, 제3자의 입장에서 인터뷰 질문에 대한 피드백을 받을 수 있어 현장에서 당황하지 않을 수 있었습니다.</p> </div>
  784. </div>
  785. </div>
  786. </div>
  787. </div>
  788. </div>
  789. </div>
  790. </div>
  791. </section>
  792. <section class="elementor-section elementor-top-section elementor-element elementor-element-3c3da3f elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="3c3da3f" data-element_type="section">
  793. <div class="elementor-container elementor-column-gap-default">
  794. <div class="elementor-row">
  795. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-13a5877" data-id="13a5877" data-element_type="column">
  796. <div class="elementor-column-wrap elementor-element-populated">
  797. <div class="elementor-widget-wrap">
  798. <div class="elementor-element elementor-element-10a483a elementor-widget elementor-widget-heading" data-id="10a483a" data-element_type="widget" data-widget_type="heading.default">
  799. <div class="elementor-widget-container">
  800. <h3 class="elementor-heading-title elementor-size-default">07. 인터뷰 환경 세팅</h3> </div>
  801. </div>
  802. </div>
  803. </div>
  804. </div>
  805. </div>
  806. </div>
  807. </section>
  808. <section class="elementor-section elementor-top-section elementor-element elementor-element-8f1e2a4 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="8f1e2a4" data-element_type="section">
  809. <div class="elementor-container elementor-column-gap-default">
  810. <div class="elementor-row">
  811. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-47ced4e" data-id="47ced4e" data-element_type="column">
  812. <div class="elementor-column-wrap elementor-element-populated">
  813. <div class="elementor-widget-wrap">
  814. <div class="elementor-element elementor-element-80f6cf1 elementor-widget elementor-widget-text-editor" data-id="80f6cf1" data-element_type="widget" data-widget_type="text-editor.default">
  815. <div class="elementor-widget-container">
  816. <div class="elementor-text-editor elementor-clearfix">
  817. <p>이번 UT는 사용자가 직접 인터뷰 장소로 방문하는 오프라인 대면 인터뷰로 진행했어요. 오프라인 대면 인터뷰를 위한 환경 세팅은 다음과 같았습니다.</p><ul><li>미팅룸 세팅</li><li>인터뷰 대상자의 행동을 관찰할 수 있도록 촬영용 카메라 세팅</li><li>인터뷰 대상자가 어떤 플로우로 Task를 진행하는지 확인할 수 있도록 테스트 기기의 화면 공유 세팅</li><li>진행자가 질문을 볼 수 있고, 서기가 답변을 작성할 수 있으며 관찰자가 메모를 할 수 있는 인터뷰 대상자의 정보가 포함된 질문지 준비</li></ul><p>인터뷰를 진행하는 모더레이터와 서기는 오프라인 미팅룸에 인터뷰 대상자와 직접 대면하여 질문을 하며 메모를 작성하고, 관찰자는 구글 밋을 통해 공유되는 화면으로 인터뷰 과정을 관찰했습니다. 관찰자 입장에서도 중간중간 궁금한 점이 있으면 공유된 시트에 추가 질문을 작성할 수 있도록 해서 모더레이터가 질문들을 확인 할 수 있도록 준비했습니다.</p> </div>
  818. </div>
  819. </div>
  820. <div class="elementor-element elementor-element-a0b9e0c elementor-widget elementor-widget-spacer" data-id="a0b9e0c" data-element_type="widget" data-widget_type="spacer.default">
  821. <div class="elementor-widget-container">
  822. <div class="elementor-spacer">
  823. <div class="elementor-spacer-inner"></div>
  824. </div>
  825. </div>
  826. </div>
  827. </div>
  828. </div>
  829. </div>
  830. </div>
  831. </div>
  832. </section>
  833. <section class="elementor-section elementor-top-section elementor-element elementor-element-1e90344 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="1e90344" data-element_type="section">
  834. <div class="elementor-container elementor-column-gap-default">
  835. <div class="elementor-row">
  836. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1abfe64" data-id="1abfe64" data-element_type="column">
  837. <div class="elementor-column-wrap elementor-element-populated">
  838. <div class="elementor-widget-wrap">
  839. <div class="elementor-element elementor-element-25f423c elementor-widget elementor-widget-heading" data-id="25f423c" data-element_type="widget" data-widget_type="heading.default">
  840. <div class="elementor-widget-container">
  841. <h2 class="elementor-heading-title elementor-size-default">UT 진행</h2> </div>
  842. </div>
  843. </div>
  844. </div>
  845. </div>
  846. </div>
  847. </div>
  848. </section>
  849. <section class="elementor-section elementor-top-section elementor-element elementor-element-322a343 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="322a343" data-element_type="section">
  850. <div class="elementor-container elementor-column-gap-default">
  851. <div class="elementor-row">
  852. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-85e5457" data-id="85e5457" data-element_type="column">
  853. <div class="elementor-column-wrap elementor-element-populated">
  854. <div class="elementor-widget-wrap">
  855. <div class="elementor-element elementor-element-36fc691 elementor-widget elementor-widget-text-editor" data-id="36fc691" data-element_type="widget" data-widget_type="text-editor.default">
  856. <div class="elementor-widget-container">
  857. <div class="elementor-text-editor elementor-clearfix">
  858. <p>저는 이번 사용성 테스트에서 UT 설계와 모더레이팅을 담당했어요. UT를 진행하는 모더레이터 입장에서 인터뷰를 어떻게 진행하고 이 과정에서 유의해야 할 부분들을 알려드릴게요.</p> </div>
  859. </div>
  860. </div>
  861. </div>
  862. </div>
  863. </div>
  864. </div>
  865. </div>
  866. </section>
  867. <section class="elementor-section elementor-top-section elementor-element elementor-element-9f3060c elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="9f3060c" data-element_type="section">
  868. <div class="elementor-container elementor-column-gap-default">
  869. <div class="elementor-row">
  870. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-508c913" data-id="508c913" data-element_type="column">
  871. <div class="elementor-column-wrap elementor-element-populated">
  872. <div class="elementor-widget-wrap">
  873. <div class="elementor-element elementor-element-2ce2347 elementor-widget elementor-widget-heading" data-id="2ce2347" data-element_type="widget" data-widget_type="heading.default">
  874. <div class="elementor-widget-container">
  875. <h3 class="elementor-heading-title elementor-size-default">01. 인터뷰 안내 및 사전 질문</h3> </div>
  876. </div>
  877. </div>
  878. </div>
  879. </div>
  880. </div>
  881. </div>
  882. </section>
  883. <section class="elementor-section elementor-top-section elementor-element elementor-element-7bf7007 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="7bf7007" data-element_type="section">
  884. <div class="elementor-container elementor-column-gap-default">
  885. <div class="elementor-row">
  886. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-29f0af8" data-id="29f0af8" data-element_type="column">
  887. <div class="elementor-column-wrap elementor-element-populated">
  888. <div class="elementor-widget-wrap">
  889. <div class="elementor-element elementor-element-e27f1ed elementor-widget elementor-widget-text-editor" data-id="e27f1ed" data-element_type="widget" data-widget_type="text-editor.default">
  890. <div class="elementor-widget-container">
  891. <div class="elementor-text-editor elementor-clearfix">
  892. <p>사전에 미리 인터뷰 방식에 대해 안내하지만 인터뷰를 시작 전 대상자에게 인터뷰 과정에 대해 한번 더 안내합니다. 또한 현장에서 궁금해하실 수 있는 촬영에 대한 부분과 관찰자가 어떤 방식으로 어떻게 참여하는지에 대해서도 안내를 합니다.</p><ul><li>지금 진행되는 인터뷰가 어떤 방식으로 진행되는지</li><li>촬영 동의 받기 및 관찰자 존재 안내</li><li>인터뷰 시작 전 스몰토크를 진행하여, 인터뷰 대상자의 배경과 상황을 파악하고 라포(rapport)를 형성</li></ul><p>인터뷰 시작 전 스몰토크를 하며 어떻게 인터뷰에 참여하게 되었는지 우리 서비스에 대해 평소에 어떻게 생각하고 사용하셨는지 대해 이야기를 나누기도 했습니다. 짧은 대화지만 우리가 의도한 리크루팅 대상자가 맞는지 스크리닝이 가능하고, 미리 준비해둔 Task와 질문을 가감하는 판단을 할 수 있습니다.</p> </div>
  893. </div>
  894. </div>
  895. </div>
  896. </div>
  897. </div>
  898. </div>
  899. </div>
  900. </section>
  901. <section class="elementor-section elementor-top-section elementor-element elementor-element-d5de48c elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="d5de48c" data-element_type="section">
  902. <div class="elementor-container elementor-column-gap-default">
  903. <div class="elementor-row">
  904. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4419491" data-id="4419491" data-element_type="column">
  905. <div class="elementor-column-wrap elementor-element-populated">
  906. <div class="elementor-widget-wrap">
  907. <div class="elementor-element elementor-element-f770baf elementor-widget elementor-widget-heading" data-id="f770baf" data-element_type="widget" data-widget_type="heading.default">
  908. <div class="elementor-widget-container">
  909. <h3 class="elementor-heading-title elementor-size-default">02. 인터뷰 진행</h3> </div>
  910. </div>
  911. </div>
  912. </div>
  913. </div>
  914. </div>
  915. </div>
  916. </section>
  917. <section class="elementor-section elementor-top-section elementor-element elementor-element-d5564b5 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="d5564b5" data-element_type="section">
  918. <div class="elementor-container elementor-column-gap-default">
  919. <div class="elementor-row">
  920. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-3be72ac" data-id="3be72ac" data-element_type="column">
  921. <div class="elementor-column-wrap elementor-element-populated">
  922. <div class="elementor-widget-wrap">
  923. <div class="elementor-element elementor-element-67f9621 elementor-widget elementor-widget-image" data-id="67f9621" data-element_type="widget" data-widget_type="image.default">
  924. <div class="elementor-widget-container">
  925. <div class="elementor-image">
  926. <figure class="wp-caption">
  927. <img width="1920" height="1080" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?fit=1920%2C1080&amp;ssl=1" class="attachment-full size-full" alt="" loading="lazy" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?w=1920&amp;ssl=1 1920w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?resize=1024%2C576&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?resize=768%2C432&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?resize=1536%2C864&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?resize=750%2C422&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?resize=1140%2C641&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-attachment-id="3603" data-permalink="https://blog.dramancompany.com/2023/09/how-to-ux-research/interview/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?fit=1920%2C1080&amp;ssl=1" data-orig-size="1920,1080" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="interview" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/interview.png?fit=1024%2C576&amp;ssl=1" /> <figcaption class="widget-image-caption wp-caption-text">실제 인터뷰 당시 모더레이터 화면에 띄워두었던 화면 세팅</figcaption>
  928. </figure>
  929. </div>
  930. </div>
  931. </div>
  932. </div>
  933. </div>
  934. </div>
  935. </div>
  936. </div>
  937. </section>
  938. <section class="elementor-section elementor-top-section elementor-element elementor-element-c81e33b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="c81e33b" data-element_type="section">
  939. <div class="elementor-container elementor-column-gap-default">
  940. <div class="elementor-row">
  941. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-abccb26" data-id="abccb26" data-element_type="column">
  942. <div class="elementor-column-wrap elementor-element-populated">
  943. <div class="elementor-widget-wrap">
  944. <div class="elementor-element elementor-element-c459b51 elementor-widget elementor-widget-text-editor" data-id="c459b51" data-element_type="widget" data-widget_type="text-editor.default">
  945. <div class="elementor-widget-container">
  946. <div class="elementor-text-editor elementor-clearfix">
  947. <ul><li><p>충분히 관찰하기</p><p>참여자마다 Task를 수행하는 시간이 다를 수 있기 때문에 모더레이터는 충분히 인터뷰 대상자가 Task를 수행하도록 기다립니다. 이 과정에서 서기는 사용자가 Task를 수행하는데 시간이 얼마나 걸렸는지, 어떤 부분에서 머뭇거리는지 어떤 과정을 거쳐 Task를 수행하는지 수행하는 과정에서 어떤 질문을 하는지 등등 모든 과정을 꼼꼼하게 관찰하고 기록합니다. 모더레이터는 실시간으로 서기가 기록하는 내용을 보면서 다음에 어떤 질문을 할지 미리 준비합니다.</p></li><li><p>질문하기</p><p>수행 과정에서 발견된 부분을 중심으로 행동에 대한 이유를 묻습니다. 이때 유도 질문을 하지 않도록 주의합니다. 실제 인터뷰를 진행할 때는 이 점에 유의해서 사용자가 직접 자신의 행동 이유나 감정 느낀 점을 설명할 수 있는 질문을 중점적으로 했습니다.</p><p>이때 준비된 질문 외에도 관찰자가 추가로 요청하는 질문을 물어보기도 합니다.</p></li><li><p>대답하기</p><p>인터뷰를 진행하다 보면 인터뷰 참가자가 제품에 대한 질문을 하기도 합니다. 이때는 바로 답변을 하기보다 ‘왜’ 그런 질문을 하게 되었는지 역으로 질문하여 사용자가 진짜 하고 싶은 이야기가 무엇인지 파악하려 했습니다. 충분히 의중을 파악한 후에 사용자가 궁금해했던 질문에 답변을 하거나 인터뷰가 완전히 끝난 뒤에 답변을 드리기도 했습니다.</p></li></ul> </div>
  948. </div>
  949. </div>
  950. </div>
  951. </div>
  952. </div>
  953. </div>
  954. </div>
  955. </section>
  956. <section class="elementor-section elementor-top-section elementor-element elementor-element-52d5a00 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="52d5a00" data-element_type="section">
  957. <div class="elementor-container elementor-column-gap-default">
  958. <div class="elementor-row">
  959. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f977a6a" data-id="f977a6a" data-element_type="column">
  960. <div class="elementor-column-wrap elementor-element-populated">
  961. <div class="elementor-widget-wrap">
  962. <div class="elementor-element elementor-element-a7e201e elementor-widget elementor-widget-heading" data-id="a7e201e" data-element_type="widget" data-widget_type="heading.default">
  963. <div class="elementor-widget-container">
  964. <h3 class="elementor-heading-title elementor-size-default">03. 인터뷰 종료</h3> </div>
  965. </div>
  966. </div>
  967. </div>
  968. </div>
  969. </div>
  970. </div>
  971. </section>
  972. <section class="elementor-section elementor-top-section elementor-element elementor-element-fbb65a9 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="fbb65a9" data-element_type="section">
  973. <div class="elementor-container elementor-column-gap-default">
  974. <div class="elementor-row">
  975. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-22013be" data-id="22013be" data-element_type="column">
  976. <div class="elementor-column-wrap elementor-element-populated">
  977. <div class="elementor-widget-wrap">
  978. <div class="elementor-element elementor-element-bbf236b elementor-widget elementor-widget-text-editor" data-id="bbf236b" data-element_type="widget" data-widget_type="text-editor.default">
  979. <div class="elementor-widget-container">
  980. <div class="elementor-text-editor elementor-clearfix">
  981. <p>준비된 Task를 진행하며 인터뷰가 충분히 진행이 되었다고 판단되면 인터뷰 대상자에게 종료 안내를 합니다. 이때 인터뷰 내용은 어떻게 보관되고 관리되는지, 사례금은 어떤 방식으로 전달되는지 한 번 더 안내를 드립니다.</p> </div>
  982. </div>
  983. </div>
  984. </div>
  985. </div>
  986. </div>
  987. </div>
  988. </div>
  989. </section>
  990. <section class="elementor-section elementor-top-section elementor-element elementor-element-122c785 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="122c785" data-element_type="section">
  991. <div class="elementor-container elementor-column-gap-default">
  992. <div class="elementor-row">
  993. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-dbcffe9" data-id="dbcffe9" data-element_type="column">
  994. <div class="elementor-column-wrap elementor-element-populated">
  995. <div class="elementor-widget-wrap">
  996. <div class="elementor-element elementor-element-2c4ba69 elementor-widget elementor-widget-heading" data-id="2c4ba69" data-element_type="widget" data-widget_type="heading.default">
  997. <div class="elementor-widget-container">
  998. <h3 class="elementor-heading-title elementor-size-default">04. 인터뷰 종료 후</h3> </div>
  999. </div>
  1000. </div>
  1001. </div>
  1002. </div>
  1003. </div>
  1004. </div>
  1005. </section>
  1006. <section class="elementor-section elementor-top-section elementor-element elementor-element-5053b18 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="5053b18" data-element_type="section">
  1007. <div class="elementor-container elementor-column-gap-default">
  1008. <div class="elementor-row">
  1009. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-099e7dc" data-id="099e7dc" data-element_type="column">
  1010. <div class="elementor-column-wrap elementor-element-populated">
  1011. <div class="elementor-widget-wrap">
  1012. <div class="elementor-element elementor-element-43bfdf9 elementor-widget elementor-widget-text-editor" data-id="43bfdf9" data-element_type="widget" data-widget_type="text-editor.default">
  1013. <div class="elementor-widget-container">
  1014. <div class="elementor-text-editor elementor-clearfix">
  1015. <p>인터뷰 종료 직후 모더레이터와 서기는 방금 진행된 인터뷰에 대해 정리하는 시간을 가집니다. 인터뷰 과정에서 부족한 부분이나 개선점은 없었는지 이야기하고 이후 진행되는 인터뷰에서 참고할 부분들을 확인합니다. 시간 여유가 있다면 실시간으로 작성했던 인터뷰 내용을 정리하기도 합니다.</p> </div>
  1016. </div>
  1017. </div>
  1018. <div class="elementor-element elementor-element-6078fb3 elementor-widget elementor-widget-spacer" data-id="6078fb3" data-element_type="widget" data-widget_type="spacer.default">
  1019. <div class="elementor-widget-container">
  1020. <div class="elementor-spacer">
  1021. <div class="elementor-spacer-inner"></div>
  1022. </div>
  1023. </div>
  1024. </div>
  1025. </div>
  1026. </div>
  1027. </div>
  1028. </div>
  1029. </div>
  1030. </section>
  1031. <section class="elementor-section elementor-top-section elementor-element elementor-element-6e6bc40 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="6e6bc40" data-element_type="section">
  1032. <div class="elementor-container elementor-column-gap-default">
  1033. <div class="elementor-row">
  1034. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-81c8bf8" data-id="81c8bf8" data-element_type="column">
  1035. <div class="elementor-column-wrap elementor-element-populated">
  1036. <div class="elementor-widget-wrap">
  1037. <div class="elementor-element elementor-element-22104cb elementor-widget elementor-widget-heading" data-id="22104cb" data-element_type="widget" data-widget_type="heading.default">
  1038. <div class="elementor-widget-container">
  1039. <h2 class="elementor-heading-title elementor-size-default">UT 분석 및 인사이트 도출</h2> </div>
  1040. </div>
  1041. </div>
  1042. </div>
  1043. </div>
  1044. </div>
  1045. </div>
  1046. </section>
  1047. <section class="elementor-section elementor-top-section elementor-element elementor-element-6862edc elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="6862edc" data-element_type="section">
  1048. <div class="elementor-container elementor-column-gap-default">
  1049. <div class="elementor-row">
  1050. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-436d09e" data-id="436d09e" data-element_type="column">
  1051. <div class="elementor-column-wrap elementor-element-populated">
  1052. <div class="elementor-widget-wrap">
  1053. <div class="elementor-element elementor-element-c8ad9e8 elementor-widget elementor-widget-text-editor" data-id="c8ad9e8" data-element_type="widget" data-widget_type="text-editor.default">
  1054. <div class="elementor-widget-container">
  1055. <div class="elementor-text-editor elementor-clearfix">
  1056. <p>인터뷰 종료 후 녹화본과 작성했던 관찰 문서를 토대로 UT 내용을 분석합니다.</p><ul><li><p>Task 달성 결과 지표 분석</p><p>각 Task 별로 사전에 정의한 성공 지표를 기준으로 인터뷰 대상자들이 얼마나 성공했는지, 공통적으로 보인 행동은 어떠했는지 내용을 작성하고 분석합니다.</p></li><li><p>Key Findings</p><p>관찰 문서를 토대로 공통적으로 발견된 현상들을 정리합니다.</p></li><li><p>인사이트 도출</p><p>위의 내용들을 조합하여 현재 피처에서 유지하는 부분과 개선이 필요한 부분들을 파악합니다.</p></li></ul> </div>
  1057. </div>
  1058. </div>
  1059. <div class="elementor-element elementor-element-53925b8 elementor-widget elementor-widget-spacer" data-id="53925b8" data-element_type="widget" data-widget_type="spacer.default">
  1060. <div class="elementor-widget-container">
  1061. <div class="elementor-spacer">
  1062. <div class="elementor-spacer-inner"></div>
  1063. </div>
  1064. </div>
  1065. </div>
  1066. </div>
  1067. </div>
  1068. </div>
  1069. </div>
  1070. </div>
  1071. </section>
  1072. <section class="elementor-section elementor-top-section elementor-element elementor-element-1936526 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="1936526" data-element_type="section">
  1073. <div class="elementor-container elementor-column-gap-default">
  1074. <div class="elementor-row">
  1075. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c8b0a4d" data-id="c8b0a4d" data-element_type="column">
  1076. <div class="elementor-column-wrap elementor-element-populated">
  1077. <div class="elementor-widget-wrap">
  1078. <div class="elementor-element elementor-element-1b45c19 elementor-widget elementor-widget-heading" data-id="1b45c19" data-element_type="widget" data-widget_type="heading.default">
  1079. <div class="elementor-widget-container">
  1080. <h2 class="elementor-heading-title elementor-size-default">UT 이후 어떤 부분이 개선되었을까요?</h2> </div>
  1081. </div>
  1082. </div>
  1083. </div>
  1084. </div>
  1085. </div>
  1086. </div>
  1087. </section>
  1088. <section class="elementor-section elementor-top-section elementor-element elementor-element-a99127c elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="a99127c" data-element_type="section">
  1089. <div class="elementor-container elementor-column-gap-default">
  1090. <div class="elementor-row">
  1091. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-739e61f" data-id="739e61f" data-element_type="column">
  1092. <div class="elementor-column-wrap elementor-element-populated">
  1093. <div class="elementor-widget-wrap">
  1094. <div class="elementor-element elementor-element-6e8e95c elementor-widget elementor-widget-image" data-id="6e8e95c" data-element_type="widget" data-widget_type="image.default">
  1095. <div class="elementor-widget-container">
  1096. <div class="elementor-image">
  1097. <img width="1920" height="1299" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?fit=1920%2C1299&amp;ssl=1" class="attachment-full size-full" alt="" loading="lazy" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?w=1920&amp;ssl=1 1920w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?resize=300%2C203&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?resize=1024%2C693&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?resize=768%2C520&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?resize=1536%2C1039&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?resize=750%2C507&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?resize=1140%2C771&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-attachment-id="3604" data-permalink="https://blog.dramancompany.com/2023/09/how-to-ux-research/solution/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?fit=1920%2C1299&amp;ssl=1" data-orig-size="1920,1299" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="solution" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?fit=300%2C203&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/09/solution.png?fit=1024%2C693&amp;ssl=1" /> </div>
  1098. </div>
  1099. </div>
  1100. </div>
  1101. </div>
  1102. </div>
  1103. </div>
  1104. </div>
  1105. </section>
  1106. <section class="elementor-section elementor-top-section elementor-element elementor-element-9d2a130 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="9d2a130" data-element_type="section">
  1107. <div class="elementor-container elementor-column-gap-default">
  1108. <div class="elementor-row">
  1109. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4ef3507" data-id="4ef3507" data-element_type="column">
  1110. <div class="elementor-column-wrap elementor-element-populated">
  1111. <div class="elementor-widget-wrap">
  1112. <div class="elementor-element elementor-element-3e7c3ee elementor-widget elementor-widget-text-editor" data-id="3e7c3ee" data-element_type="widget" data-widget_type="text-editor.default">
  1113. <div class="elementor-widget-container">
  1114. <div class="elementor-text-editor elementor-clearfix">
  1115. <p>UT를 통해 변경된 대표적인 예는 &#8216;오늘의 소식&#8217; 영역입니다.</p><p>저희는 매일 사용자가 가장 먼저 확인해야 할 소식을 가장 잘 보이는 곳에 안내함으로써 빠르게 소식을 확인하고 상세 내용에 접근할 수 있도록 의도했지만 실제 UT에서는 사용자가 해당 영역 자체를 인지하지 못하거나 광고로 인지하는 경우가 많았습니다.</p><p>이후 기존안과 해당 영역을 다른 콘텐츠와 동일한 형태로 제공하는 안을 비교하는 A/B 테스트를 진행했습니다. 기존의 상단 영역에서 안내할 때보다 콘텐츠 형태로 제공했을 때 60% 더 많은 전환율(노출 고객 대비 클릭 률)이 일어나는 것을 확인하고 개선안을 100% 배포하는 결정을 할 수 있었습니다.</p> </div>
  1116. </div>
  1117. </div>
  1118. <div class="elementor-element elementor-element-e138166 elementor-widget elementor-widget-spacer" data-id="e138166" data-element_type="widget" data-widget_type="spacer.default">
  1119. <div class="elementor-widget-container">
  1120. <div class="elementor-spacer">
  1121. <div class="elementor-spacer-inner"></div>
  1122. </div>
  1123. </div>
  1124. </div>
  1125. </div>
  1126. </div>
  1127. </div>
  1128. </div>
  1129. </div>
  1130. </section>
  1131. <section class="elementor-section elementor-top-section elementor-element elementor-element-886372e elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="886372e" data-element_type="section">
  1132. <div class="elementor-container elementor-column-gap-default">
  1133. <div class="elementor-row">
  1134. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-82ebe59" data-id="82ebe59" data-element_type="column">
  1135. <div class="elementor-column-wrap elementor-element-populated">
  1136. <div class="elementor-widget-wrap">
  1137. <div class="elementor-element elementor-element-6116c66 elementor-widget elementor-widget-heading" data-id="6116c66" data-element_type="widget" data-widget_type="heading.default">
  1138. <div class="elementor-widget-container">
  1139. <h2 class="elementor-heading-title elementor-size-default">글을 마치며</h2> </div>
  1140. </div>
  1141. </div>
  1142. </div>
  1143. </div>
  1144. </div>
  1145. </div>
  1146. </section>
  1147. <section class="elementor-section elementor-top-section elementor-element elementor-element-cd5d2bf elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="cd5d2bf" data-element_type="section">
  1148. <div class="elementor-container elementor-column-gap-default">
  1149. <div class="elementor-row">
  1150. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e3e1437" data-id="e3e1437" data-element_type="column">
  1151. <div class="elementor-column-wrap elementor-element-populated">
  1152. <div class="elementor-widget-wrap">
  1153. <div class="elementor-element elementor-element-8006147 elementor-widget elementor-widget-text-editor" data-id="8006147" data-element_type="widget" data-widget_type="text-editor.default">
  1154. <div class="elementor-widget-container">
  1155. <div class="elementor-text-editor elementor-clearfix">
  1156. <p>UX리서처없이 리멤버 프로덕트 디자이너는 어떻게 사용자 테스트를 하는지 소개했어요. 리멤버에서는 UT뿐만 아니라 설문조사, 인터뷰, A/B 테스트 등 다양한 리서치를 진행하며 사용자를 좀 더 이해하고 사용자를 위한 의사결정을 하기 위한 노력들을 하고 있어요. 앞으로도 더 많은 사용자의 피드백을 통해 발전하는 리멤버를 기대해 주세요.</p> </div>
  1157. </div>
  1158. </div>
  1159. </div>
  1160. </div>
  1161. </div>
  1162. </div>
  1163. </div>
  1164. </section>
  1165. <section class="elementor-section elementor-top-section elementor-element elementor-element-b1e7b2c elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="b1e7b2c" data-element_type="section">
  1166. <div class="elementor-container elementor-column-gap-default">
  1167. <div class="elementor-row">
  1168. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c7cadc7" data-id="c7cadc7" data-element_type="column">
  1169. <div class="elementor-column-wrap elementor-element-populated">
  1170. <div class="elementor-widget-wrap">
  1171. <div class="elementor-element elementor-element-693d68c elementor-widget elementor-widget-spacer" data-id="693d68c" data-element_type="widget" data-widget_type="spacer.default">
  1172. <div class="elementor-widget-container">
  1173. <div class="elementor-spacer">
  1174. <div class="elementor-spacer-inner"></div>
  1175. </div>
  1176. </div>
  1177. </div>
  1178. </div>
  1179. </div>
  1180. </div>
  1181. </div>
  1182. </div>
  1183. </section>
  1184. </div>
  1185. </div>
  1186. </div>
  1187. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2023/09/how-to-ux-research/">리멤버에서 UT(사용자 테스트)는 어떻게 진행하나요?</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1188. ]]></content:encoded>
  1189. <wfw:commentRss>https://blog.dramancompany.com/2023/09/how-to-ux-research/feed/</wfw:commentRss>
  1190. <slash:comments>1</slash:comments>
  1191. <post-id xmlns="com-wordpress:feed-additions:1">3594</post-id> </item>
  1192. <item>
  1193. <title>리멤버 웹 서비스 좌충우돌 Yarn Berry 도입기</title>
  1194. <link>https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/</link>
  1195. <comments>https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/#comments</comments>
  1196. <dc:creator><![CDATA[종택 오]]></dc:creator>
  1197. <pubDate>Wed, 22 Feb 2023 02:30:29 +0000</pubDate>
  1198. <category><![CDATA[Tech]]></category>
  1199. <category><![CDATA[frontend]]></category>
  1200. <category><![CDATA[yarn]]></category>
  1201. <category><![CDATA[yarn berry]]></category>
  1202. <category><![CDATA[개발문화]]></category>
  1203. <category><![CDATA[리멤버]]></category>
  1204. <category><![CDATA[리멤버 웹]]></category>
  1205. <category><![CDATA[리멤버 채용]]></category>
  1206. <category><![CDATA[패키지 매니저]]></category>
  1207. <category><![CDATA[프론트엔드]]></category>
  1208. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3445</guid>
  1209.  
  1210. <description><![CDATA[<p>안녕하세요. 드라마앤컴퍼니에서 현재 채용 서비스를 개발하고 있는 웹 프론트엔드 개발자 오종택입니다. 이전에는 동료 분들의 비즈니스 임팩트를 극대화 하기 위한 UTS(User Targeting System, 조건에 맞는 유저를 찾아주는 쿼리 빌더) 등의 인터널 제품을 만들기도 했습니다. 리멤버 웹 팀은 리멤버 블랙, 리멤버 채용 솔루션 등 모든 서비스의 웹 애플리케이션을 개선 발전시키는 업무를 담당하고 있습니다. 이 과정에서 고객의 제품 [&#8230;]</p>
  1211. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/">리멤버 웹 서비스 좌충우돌 Yarn Berry 도입기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1212. ]]></description>
  1213. <content:encoded><![CDATA[
  1214. <p>안녕하세요. 드라마앤컴퍼니에서 현재 채용 서비스를 개발하고 있는 웹 프론트엔드 개발자 오종택입니다. 이전에는 동료 분들의 비즈니스 임팩트를 극대화 하기 위한 UTS(User Targeting System, 조건에 맞는 유저를 찾아주는 쿼리 빌더) 등의 인터널 제품을 만들기도 했습니다.</p>
  1215.  
  1216.  
  1217.  
  1218. <p>리멤버 웹 팀은 리멤버 블랙, 리멤버 채용 솔루션 등 모든 서비스의 웹 애플리케이션을 개선 발전시키는 업무를 담당하고 있습니다. 이 과정에서 고객의 제품 경험을 개선하고, 이러한 개선 활동을 원활하게 지원할 수 있도록 팀의 생산성을 개선하는 일을 중요한 어젠다로 보고 있습니다.</p>
  1219.  
  1220.  
  1221.  
  1222. <p>최근에는 기존에 사용하던 패키지 매니저인 <code>yarn</code> 을 최신 버전인 <code>yarn berry</code> 로 마이그레이션 하기도 했습니다. 처음 <code>yarn berry</code> 라는 키워드를 접했을 땐, 빌드 시간을 일부 단축 시켜주고 개발 과정에서의 안정성을 높여줄 수 있다는 점에서 관심을 가지게 되었습니다.</p>
  1223.  
  1224.  
  1225.  
  1226. <p>새로운 기술은 이후에 일어날 수 있는 변화를 미리 생각해서 신중하게 도입해야 할 것입니다. 웹 파트는 지속적으로 기술을 습득하고 지식을 공유하며, 팀이 효과적으로 일할 수 있다고 판단한 기술은 빠르게 개념 증명(PoC)을 진행하여 기술의 이해도를 높여가고 있습니다.</p>
  1227.  
  1228.  
  1229.  
  1230. <p>현재 리멤버 웹 파트는 모노레포 도입을 준비하면서 <code>pnpm</code> + <code>Turborepo</code>(<a href="https://turbo.build/">링크</a>) 조합을 선택하게 되어 <code>yarn berry</code>는 사용하지 않게 되었습니다. 이러한 시도가 있었기에 프로덕션 레벨에서 패키지 매니저를 교체하면서 해당 기술에 대한 이해도를 높였고 이를 바탕으로 최종적으로는 가장 만족스러운 결론에 다다를 수 있었습니다.</p>
  1231.  
  1232.  
  1233.  
  1234. <p>이번 글에서는 리멤버 웹 서비스에 점진적으로 <code>yarn berry</code> 를 적용한 과정과, 트러블 슈팅 과정을 겪으며 느꼈던 점들을 공유드리고자 합니다.</p>
  1235.  
  1236.  
  1237.  
  1238. <h2>1. Yarn Berry를 써야 할 결심</h2>
  1239.  
  1240.  
  1241.  
  1242. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?ssl=1"><img data-attachment-id="3552" data-permalink="https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/image-2-5/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?fit=1370%2C682&amp;ssl=1" data-orig-size="1370,682" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?fit=300%2C149&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?fit=1024%2C510&amp;ssl=1" loading="lazy" width="1024" height="510" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=1024%2C510&#038;ssl=1" alt="" class="wp-image-3552" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=1024%2C510&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=300%2C149&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=768%2C382&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=360%2C180&amp;ssl=1 360w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=750%2C373&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?resize=1140%2C568&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-2.png?w=1370&amp;ssl=1 1370w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>제로 인스톨로 탄소 감축 :가보자고:</figcaption></figure></div>
  1243.  
  1244.  
  1245.  
  1246. <p>여러 아티클을 살펴보니 <code>yarn berry</code> 를 사용하면 빌드 시간을 평균적으로 1분 정도 단축할 수 있는 것으로 보였습니다. 뿐만 아니라 종속성들을 보다 안전하게 관리하면서도 기존 node_modules에 딸려오는 여러가지 골치 아픈 문제들을 근본적으로 해결할 수도 있을 것으로 봤습니다.</p>
  1247.  
  1248.  
  1249.  
  1250. <p>업무 기록을 살펴보니 유사한 고민이 과거에도 있었으나 당시 몇 명 없는 인원으로 운영되던 터라 개발 인프라 단에 리소스를 투자하기 어려운 상황이었기 때문에 우선 순위에서 밀렸던 것 같았습니다. 이제 그 때에 비해 프론트엔드 개발자도 늘었고, 개선 시 얻을 수 있는 임팩트도 커졌으니 명분도 충분했습니다. yarn berry 기술 자체도 처음 발표 때와 비교하여 어느 정도 관련 자료도 늘고 성숙해졌다는 판단 또한 있었습니다.</p>
  1251.  
  1252.  
  1253.  
  1254. <p>기존 리멤버의 웹 서비스는 yarn 1.x 버전의 패키지 매니저를 사용해왔습니다. 현재 yarn 1.x 버전은 classic 으로 명명되었으며, 새로운 기능 개발은 이루어지지 않고 유지보수만 이루어지는 레거시 프로젝트가 되었습니다. 즉, yarn classic을 사용하고 있는 상황이고, yarn berry냐 pnpm이냐 하는 선택지를 고민하는게 아니라면 점진적으로 berry로 마이그레이션하는게 바람직하다고 생각합니다.</p>
  1255.  
  1256.  
  1257.  
  1258. <p>(참고로 새 프로젝트를 만드는 시점이라면 <code>yarn init -2</code> 명령으로 간단하게 프로젝트를 생성할 수 있습니다. 해당 프로젝트에 대한 보다 상세한 정보는 <a href="https://github.com/yarnpkg/berry">yarnpkg/berry</a> 에서 확인하실 수 있습니다.)</p>
  1259.  
  1260.  
  1261.  
  1262. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215241351-e7c73027-f829-459c-ab1e-f6e2d15f474c.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>yarn classic 레포지토리. 기능 개발이 중단되었음을 알리는 디스크립션이 붙어있다.</figcaption></figure></div>
  1263.  
  1264.  
  1265.  
  1266. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215241355-efcfd03d-1b08-4e64-a875-acf658c21eb8.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>yarn berry 레포지토리. yarn classic과는 대조되는 &#8216;Active development&#8217; 문구가 붙어있다.</figcaption></figure></div>
  1267.  
  1268.  
  1269.  
  1270. <h2>2. Why ‘Yarn Berry’</h2>
  1271.  
  1272.  
  1273.  
  1274. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/219931631-edf19a25-06cd-4553-a6ba-88befa0ac587.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>빠른 찍먹 후 공부를 곁들인&#8230;</figcaption></figure></div>
  1275.  
  1276.  
  1277.  
  1278. <p>도입을 결심한 뒤 개발이 비교적 적게 일어나고, 변경으로 인한 리스크가 적은 어드민 및 내부 라이브러리 프로젝트 부터 점진적으로 적용을 시작해나갔습니다. <code>yarn berry</code>를 적용하는 한편으로는 내부 공유를 위한 스터디 자료 준비가 이루어졌습니다.</p>
  1279.  
  1280.  
  1281.  
  1282. <p>적용 과정에서 패키지 매니저의 특징에 대해 자세히 살펴볼 수 있었습니다. yarn의 새로운 버전은 <code>node_modules</code> 라는 설계 그 자체로 인해 생기는 막대한 비효율을 해결하고자 기획 되었습니다. 물론 <code>npm</code> 은 그간 Node 생태계를 위해 많은 일을 해왔지만 가장 첫 번째로 꼽힐 용량 문제를 제외하고서라도 많은 문제를 안고 있었습니다. 아래는 <a href="https://yarnpkg.com/features/pnp">yarn 공식 문서</a>에 언급되어 있는 내용에 대한 정리입니다.</p>
  1283.  
  1284.  
  1285.  
  1286. <h3>1) 모듈 탐색 과정의 비효율</h3>
  1287.  
  1288.  
  1289.  
  1290. <p>node_modules 구조 하에서 모듈을 검색하는 방식은 기본적으로 디스크 I/O 작업입니다. 이는 node_modules가 가진 문제이기 때문에 yarn classic과 npm 모두에 해당되는 내용입니다.</p>
  1291.  
  1292.  
  1293.  
  1294. <p>개발자가 node_modules 내부에서 특정 라이브러리를 불러오는 상황을 가정해보겠습니다. Node.js가 모듈을 불러올 때 경로 탐색에 사용하는 몇 가지 규칙이 있는데요. 이 규칙은 <a href="https://nodejs.org/api/modules.html#loading-from-node_modules-folders">Node.js 공식 문서</a>에서 확인할 수 있습니다. <code>require()</code>의 경우 1) fs, http 등의 코어 모듈이 아니면서, 2) 절대 경로를 사용할 경우 대략 아래와 같은 순서로 순회하며 모듈을 검색합니다.</p>
  1295.  
  1296.  
  1297.  
  1298. <p>다음은 <code>'/home/ry/projects/foo.js'</code> 에서 <code>require('bar.js')</code> 를 탐색할 경우입니다.</p>
  1299.  
  1300.  
  1301.  
  1302. <ul><li><code>/home/ry/projects/node_modules/bar.js</code></li></ul>
  1303.  
  1304.  
  1305.  
  1306. <ul><li><code>/home/ry/node_modules/bar.js</code></li></ul>
  1307.  
  1308.  
  1309.  
  1310. <ul><li><code>/home/node_modules/bar.js</code></li></ul>
  1311.  
  1312.  
  1313.  
  1314. <ul><li><code>/node_modules/bar.js</code></li></ul>
  1315.  
  1316.  
  1317.  
  1318. <p>이처럼 매 탐색마다 수 많은 폴더와 파일을 실제로 열고 닫으면서 검색할 수 밖에 없으며, node_modules 중첩 등 경우에 따라서는 순회해야 하는 경로가 이보다 복잡해질 수 있습니다.</p>
  1319.  
  1320.  
  1321.  
  1322. <p>패키지 설치 과정의 경우에도 마찬가지 입니다. 설치 과정에 필요한 최소 동작만으로도 이미 비용이 많이 들고 있기 때문에 각 패키지 간 의존 관계가 유효한지 등의 추가적인 검증에 리소스를 할당하기 어렵습니다.</p>
  1323.  
  1324.  
  1325.  
  1326. <p>이처럼 모듈 탐색을 메모리 상에서 자료구조로 처리하지 않고 I/O로 직접 처리하다보니 추가적인 최적화가 어렵습니다. 실제로 yarn 개발진은 이러한 이유들로 더 이상 최적화 할 여지가 없었다고 문서에서 밝히고 있습니다. yarn berry에서는 이 뒤에서 언급될 PnP 라는 기술을 통해 이를 개선합니다.</p>
  1327.  
  1328.  
  1329.  
  1330. <h3>2) 유령 의존성 (Phantom Dependency)</h3>
  1331.  
  1332.  
  1333.  
  1334. <p>물론 npm은 속도 문제를 개선하기 위해 호이스팅 등 최적화 알고리즘을 도입하였으나 부작용으로 <code>유령 의존성</code> 이라는 문제를 새로 낳고 말았습니다.</p>
  1335.  
  1336.  
  1337.  
  1338. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://classic.yarnpkg.com/assets/posts/2018-02-15-nohoist/standalone-2.svg" alt=""/><figcaption>https://classic.yarnpkg.com/blog/2018/02/15/nohoist/</figcaption></figure></div>
  1339.  
  1340.  
  1341.  
  1342. <p>npm, yarn classic 등은 중복 설치를 방지하기 위해 위 그림처럼 종속성 트리 아래에 존재하는 패키지들을 호이스팅 &amp; 병합합니다. 그렇게 하면 패키지 최상위에서 트리 깊이 탐색하지 않고 루트 경로에서 원하는 패키지를 탐색할 수 있으므로 효율적입니다.</p>
  1343.  
  1344.  
  1345.  
  1346. <p>하지만 이런 효율의 반대 급부로는 직접 설치하지 않고, 간접 설치한 종속성에 개발자가 접근할 수 있게 되는 상황이 벌어지기도 합니다. 존재하지 않는 종속성에 의존하는 코드가 왕왕 발생할 수 있다는 뜻입니다. 이를 <code>유령 의존성</code> 이라고 합니다. 앞서 언급한 node_modules의 단점으로 인해 의존성 트리의 유효성을 검증하기 어렵다는 것도 한 몫을 했습니다.</p>
  1347.  
  1348.  
  1349.  
  1350. <p>yarn berry에서는 이런 식의 호이스팅 동작이 일어나지 않도록 <code>nohoist</code> 옵션이 기본적으로 활성화 되어 있습니다.</p>
  1351.  
  1352.  
  1353.  
  1354. <h3>3) Plug&#8217;n&#8217;Play (PnP)</h3>
  1355.  
  1356.  
  1357.  
  1358. <ul><li><a href="https://yarnpkg.com/features/pnp" target="_blank" rel="noreferrer noopener">https://yarnpkg.com/features/pnp</a></li><li><a href="https://classic.yarnpkg.com/lang/en/docs/pnp/" target="_blank" rel="noreferrer noopener">https://classic.yarnpkg.com/lang/en/docs/pnp/</a></li><li><a href="https://github.com/yarnpkg/berry/issues/850" target="_blank" rel="noreferrer noopener">https://github.com/yarnpkg/berry/issues/850</a></li></ul>
  1359.  
  1360.  
  1361.  
  1362. <p>yarn berry는 <strong>Plug&#8217;n&#8217;Play(PnP)</strong> 라는 기술을 사용하여 이러한 문제들을 해결합니다. yarn berry는 node_modules를 사용하지 않습니다. 대신 <code>.yarn</code> 경로 하위에 의존성들을 <code>.zip</code> 포맷으로 압축 저장하고, <code>.pnp.cjs</code> 파일을 생성 후 의존성 트리 정보를 단일 파일에 저장합니다. 이를 <code>인터페이스 링커 (Interface Linker)</code> 라고 합니다.</p>
  1363.  
  1364.  
  1365.  
  1366. <blockquote class="wp-block-quote"><p><em>Linkers are the glue between the logical dependency tree and the way it&#8217;s represented on the filesystem. Their main use is to take the package data and put them on the filesystem in a way that their target environment will understand (for example, in Node&#8217;s case, it will be to generate a .pnp.cjs file).</em></p><cite>https://yarnpkg.com/api/interfaces/yarnpkg_core.linker.html</cite></blockquote>
  1367.  
  1368.  
  1369.  
  1370. <p>링커를 논리적 종속성 트리와 파일 시스템 사이에 있는 일종의 접착제로도 비유할 수 있습니다. 이러한 링커를 사용함으로서 패키지를 검색하기 위한 비효율적이고 반복적인 디스크 I/O로부터 벗어날 수 있게 되었습니다. 의존성 또한 쉽게 검증할 수 있어 유령 의존성 문제도 해결 가능해졌습니다.</p>
  1371.  
  1372.  
  1373.  
  1374. <p>아래 코드는 pnp.cjs의 일부입니다</p>
  1375.  
  1376.  
  1377.  
  1378. <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">      ["@babel/helper-module-transforms", [\
  1379.        ["npm:7.19.6", {\
  1380.          "packageLocation": "./.yarn/cache/@babel-helper-module-transforms-npm-7.19.6-c73ab63519-c28692b37d.zip/node_modules/@babel/helper-module-transforms/",\
  1381.          "packageDependencies": [\
  1382.            ["@babel/helper-module-transforms", "npm:7.19.6"],\
  1383.            ["@babel/helper-environment-visitor", "npm:7.18.9"],\
  1384.            ["@babel/helper-module-imports", "npm:7.18.6"],\
  1385.            ["@babel/helper-simple-access", "npm:7.19.4"],\
  1386.            ["@babel/helper-split-export-declaration", "npm:7.18.6"],\
  1387.            ["@babel/helper-validator-identifier", "npm:7.19.1"],\
  1388.            ["@babel/template", "npm:7.18.10"],\
  1389.            ["@babel/traverse", "npm:7.19.6"],\
  1390.            ["@babel/types", "npm:7.20.2"]\
  1391.          ],\
  1392.          "linkType": "HARD"\
  1393.        }]\
  1394.      ]],\
  1395.      ["@babel/helper-optimise-call-expression", [\
  1396.        ["npm:7.18.6", {\
  1397.          "packageLocation": "./.yarn/cache/@babel-helper-optimise-call-expression-npm-7.18.6-65705387c4-e518fe8418.zip/node_modules/@babel/helper-optimise-call-expression/",\
  1398.          "packageDependencies": [\
  1399.            ["@babel/helper-optimise-call-expression", "npm:7.18.6"],\
  1400.            ["@babel/types", "npm:7.20.2"]\
  1401.          ],\
  1402.          "linkType": "HARD"\
  1403.        }]\
  1404.      ]],\</pre>
  1405.  
  1406.  
  1407.  
  1408. <p>위와 같이 .pnp.cjs는 의존성 트리를 중첩된 맵으로 표현하였습니다. 기존 Node 가 파일시스템에 접근하여 직접 I/O 를 실행하던 require 문의 비효율을 자료구조를 메모리에 올리는 방식으로 탐색을 최적화한 것입니다. 의존성 압축을 통하여 디스크 용량 절감 효과도 볼 수 있습니다. <code>du -sh</code> 명령어로 확인해보았을 때, Next.js 기반 어드민 서비스 기준 <code>913MB → 247MB</code> 로 기존 패키지 용량 대비 약 <code>27%</code> 수준으로 패키지 관련 용량이 감소한 것을 확인할 수 있습니다.</p>
  1409.  
  1410.  
  1411.  
  1412. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215241955-a7b64cd0-e15c-49c8-8a0a-b7746d5625a3.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>.yarn/cache에 다운로드 된 종속성들</figcaption></figure></div>
  1413.  
  1414.  
  1415.  
  1416. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215241959-a17f711b-66f1-4494-810f-9f70744d039c.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>yarn classic 에서의 node_modules 크기 (913MB)</figcaption></figure></div>
  1417.  
  1418.  
  1419.  
  1420. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215241967-11476f03-2757-4aaf-9913-323f64fc87a4.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>yarn berry 에서의 .yarn 크기 (247MB)</figcaption></figure></div>
  1421.  
  1422.  
  1423.  
  1424. <p>다만 .yarnrc.yml의 링커 설정을 pnp가 아닌 <code>node-modules</code> 로 하게 된다면 기존처럼 node_modules를 설치하여 의존성을 관리하게 됩니다. 하지만 이렇게 사용할 경우 앞서 설명드린 PnP의 장점들을 활용하지 못하게 됩니다.</p>
  1425.  
  1426.  
  1427.  
  1428. <p>이에 대한 예시로 최근 `Vercel` 에서 모노레포 툴링으로 발표한 <code>Turborepo</code> 의 경우 패키지 매니저 중 <code>pnpm</code> 의 pnp 모드만 지원하고 있고, 메인테이너는 yarn berry의 경우 지원 계획을 취소한 상태입니다. 이 경우 앞서 말씀드린 방식으로 berry를 사용해야 합니다. 관련 이슈는 <a href="https://github.com/vercel/turbo/issues/693#issuecomment-1278886166" target="_blank" rel="noreferrer noopener">여기</a>에서 확인하실 수 있습니다.</p>
  1429.  
  1430.  
  1431.  
  1432. <h3>4) Zero-Installs</h3>
  1433.  
  1434.  
  1435.  
  1436. <ul><li><a href="https://yarnpkg.com/features/zero-installs" target="_blank" rel="noreferrer noopener">https://yarnpkg.com/features/zero-installs</a></li></ul>
  1437.  
  1438.  
  1439.  
  1440. <p><code>.yarn</code> 폴더에 받아놓은 파일들은 오프라인 캐시 역할 또한 할 수 있습니다. 커밋에 포함시켜 github에 프로젝트 코드와 함께 올려두면 어디서든 같은 환경에서 실행 가능할 것을 보장할 수 있으며 별도의 설치 과정도 필요가 없습니다.</p>
  1441.  
  1442.  
  1443.  
  1444. <p>만약 의존성에 변경이 발생하더라도 git 상에서 diff로 잡히므로 쉽게 파악 가능합니다. 개발자들 간 node_modules가 동일한지 체크할 필요가 없다는 뜻입니다.</p>
  1445.  
  1446.  
  1447.  
  1448. <p>제가 생각했을 때 Yarn berry 도입 시 가장 강조되어야 할 중요한 지점이라고 생각합니다. 우리가 작성한 코드들이 여러 툴체인을 거치는 동안 많은 파일들이 generate 되는데, 만약 로컬에 설치된 파일과 리모트(CI 환경, 실서비스 등)에 설치된 파일이 달라 디버깅을 어렵게 한다면 대응하기 매우 어려워질 것입니다. Zero Install을 사용하게 된다면 어떤 설치 환경에서든 같은 상황임을 명시적으로 보장할 수 있습니다.</p>
  1449.  
  1450.  
  1451.  
  1452. <p>부가적인 장점으로 현재 브랜치에 맞는 package.json에 맞게 node_modules를 갱신하기 위한 반복적인 yarn install을 할 필요 또한 없습니다. 브랜치를 체크아웃할 때마다 <code>.yarn/cache</code> 폴더에 있는 의존성도 커밋으로 잡혀있기 때문에 여타 파일들처럼 파일로 취급되어 함께 변경되기 때문입니다.</p>
  1453.  
  1454.  
  1455.  
  1456. <h2>3. 적용 방법</h2>
  1457.  
  1458.  
  1459.  
  1460. <p><a href="https://yarnpkg.com/features/pnp#compatibility-table)" target="_blank" rel="noreferrer noopener">호환성 테이블</a> 에서 지원하는 버전에 해당만 한다면 마이그레이션 자체는 어렵지 않습니다. <code>yarn</code>이 이미 설치되어 있다는 가정 하에 <a href="https://yarnpkg.com/getting-started/migration" target="_blank" rel="noreferrer noopener">yarn 공식 문서</a> 에서 설명하는 대로 진행합니다.</p>
  1461.  
  1462.  
  1463.  
  1464. <p>정말 해결할 수 없는 문제가 있다면 <code>.yarnrc.yml</code> 에서 <code>nodeLinker</code> 설정을 <code>loose</code> 혹은 <code>node-modules</code> 로 바꿔야(<a href="https://yarnpkg.com/getting-started/migration#if-required-enable-the-node-modules-plugin" target="_blank" rel="noreferrer noopener">링크</a>) 합니다.</p>
  1465.  
  1466.  
  1467.  
  1468. <pre class="wp-block-code"><code>nodeLinker : "pnp" # 혹은 "node-modules"</code></pre>
  1469.  
  1470.  
  1471.  
  1472. <p>위에서 설명 드린 유령 의존성 문제 등의 이유로 현재 깨져 있는 종속성 트리를 수동으로 추가해주어야 하는 경우가 있을 수 있습니다. 이때는 일반적인 설치 방식으로 package.json에 종속성으로 추가해주거나, packageExtensions를 사용(<a href="https://yarnpkg.com/getting-started/migration#a-package-is-trying-to-access-another-package-" target="_blank" rel="noreferrer noopener">링크</a>)하여 보완해줄 수 있습니다.</p>
  1473.  
  1474.  
  1475.  
  1476. <pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">packageExtensions:
  1477.  "debug@*":
  1478.    peerDependenciesMeta:
  1479.      "supports-color":
  1480.        optional: true</pre>
  1481.  
  1482.  
  1483.  
  1484. <h3>1) yarn 버전 변경</h3>
  1485.  
  1486.  
  1487.  
  1488. <pre class="wp-block-code"><code>&gt; yarn set version berry</code></pre>
  1489.  
  1490.  
  1491.  
  1492. <p>이미 .yarnrc.yml 등 berry 관련된 파일이 생성되어 있으면 작동하지 않습니다. 만약 v1.x로 돌아가려면 <code>yarn set version classic</code> 을 입력합니다.</p>
  1493.  
  1494.  
  1495.  
  1496. <h3>2) <code>.gitignore</code> 설정</h3>
  1497.  
  1498.  
  1499.  
  1500. <p><a href="https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored" target="_blank" rel="noreferrer noopener">문서</a>(Zero-Installs 기준)를 따라 <code>.gitignore</code> 에 아래 경로를 추가해줍니다. <code>!</code> 는 제외할(gitignore) 경로에서 빼달라는 뜻이므로 <code>.yarn</code> 이하 경로 중 포함시킬 경로들을 명시한 것으로 생각하시면 됩니다. 부정의 부정이라 좀 혼란스러울 수는 있을 것 같습니다. 각 경로의 역할에 대한 자세한 설명은 공식 문서에서 확인하실 수 있습니다.</p>
  1501.  
  1502.  
  1503.  
  1504. <pre class="wp-block-code"><code>.yarn/*
  1505. !.yarn/cache
  1506. !.yarn/patches
  1507. !.yarn/plugins
  1508. !.yarn/releases
  1509. !.yarn/sdks
  1510. !.yarn/versions</code></pre>
  1511.  
  1512.  
  1513.  
  1514. <h3>3) <code>.npmrc</code>, <code>.yarnrc</code>를 <code>.yarnrc.yml</code> 로 마이그레이션</h3>
  1515.  
  1516.  
  1517.  
  1518. <p>berry로 버전을 변경하게 되면 루트 경로에 .yarnrc.yml 파일이 생성됩니다. 기존에 있던 .npmrc, .yarnrc는 지원하지 않기 때문에 <a href="https://yarnpkg.com/configuration/yarnrc" target="_blank" rel="noreferrer noopener">문서</a>를 확인하여 각각의 옵션을 마이그레이션 해주면 됩니다.</p>
  1519.  
  1520.  
  1521.  
  1522. <p>.yarnrc.yml에서 nodeLinker를 <code>node-modules</code> 로 입력하면 classic에서 하던 대로 종속성들을 node_modules에서 관리하게 됩니다. pnp 모드를 사용할 것이므로 <code>pnp</code> 라고 적혀 있는지 확인합니다.</p>
  1523.  
  1524.  
  1525.  
  1526. <p>또한 저희 프로젝트에서는 github packages로 배포한 종속성을 포함하고 있어 <code>yarnrc.yml</code> 에 추가적으로 관련 설정을 추가해줍니다. 배포 시에는 <code>Dockerfile</code> 에서 토큰 값을 넣어줍니다.</p>
  1527.  
  1528.  
  1529.  
  1530. <pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">nodeLinker: pnp
  1531.  
  1532. yarnPath: .yarn/releases/yarn-3.3.0.cjs
  1533.  
  1534. npmScopes:
  1535.  organization이름(ex. dramancompany):
  1536.    npmAlwaysAuth: true
  1537.    # NOTE: 로컬에서 설치 시 터미널에 'export NPM_AUTH_TOKEN=...' 명령어로 환경변수를 설정
  1538.    npmAuthToken: ${NPM_AUTH_TOKEN} # https://github.com/yarnpkg/berry/pull/1341
  1539.    npmRegistryServer: 'https://npm.pkg.github.com'</pre>
  1540.  
  1541.  
  1542.  
  1543. <p>상기 세팅이 모두 끝나면 `yarn install` 을 입력하여 yarn classic에서 berry로 마이그레이션을 진행합니다.</p>
  1544.  
  1545.  
  1546.  
  1547. <pre class="wp-block-code"><code>&gt; yarn install</code></pre>
  1548.  
  1549.  
  1550.  
  1551. <p>이 과정에서 깨진 의존성들이 발견되곤 합니다. <code>styled-components</code> 사용 시 <code>react-is</code> 를 설치하라는 에러 메시지가 뜨는 것이 대표적인 케이스입니다. 터미널에 뜨는 에러 메시지를 확인하여 필요한 의존성들을 추가 설치해줍니다.</p>
  1552.  
  1553.  
  1554.  
  1555. <pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">packageExtensions:
  1556.  styled-components@*:
  1557.    dependencies:
  1558.      react-is: '*'</pre>
  1559.  
  1560.  
  1561.  
  1562. <p>설치 시 <code>~/.yarn/berry/cache</code> 전역 경로에도 함께 설치가 되므로 <code>yarn cache clean</code> 등의 명령어를 통해 의존성이 완전히 설치되지 않은 상황을 재현하고 싶을 경우 <code>yarn cache clean --mirror</code> 를 입력(<a href="https://yarnpkg.com/features/offline-cache#cleaning-the-cache" target="_blank" rel="noreferrer noopener">관련 문서</a>)해야 하므로 유의할 필요가 있습니다.</p>
  1563.  
  1564.  
  1565.  
  1566. <p>여기까지 마무리 되었으면 한번 커밋하여 진행 상황을 저장합니다.</p>
  1567.  
  1568.  
  1569.  
  1570. <h3>4) yarn berry를 IDE와 통합 (with. TypeScript)</h3>
  1571.  
  1572.  
  1573.  
  1574. <p>지금까지는 패키지 매니저 레벨에서 마이그레이션 할 것들을 처리해주었습니다. 이제 IDE에 의존성과 타입 정보를 node_modules가 아닌 .yarn에서 읽어오도록 알려주어야 합니다. VSCode 기준으로 설명하겠습니다.<br>일단 아래 세 가지 요소들을 설치합니다.</p>
  1575.  
  1576.  
  1577.  
  1578. <p>1. <code>VSCode Extension에서 ZipFS 설치</code> (zip 파일로 설치된 종속성을 읽어올 수 있도록)</p>
  1579.  
  1580.  
  1581.  
  1582. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242255-06b1fe32-b8df-4434-816e-7d0c7b0bd779.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>ZipFS 설치</figcaption></figure></div>
  1583.  
  1584.  
  1585.  
  1586. <p>2. <code>yarn install -D typescript eslint prettier</code></p>
  1587.  
  1588.  
  1589.  
  1590. <p>3. <code>yarn dlx @yarnpkg/sdks vscode</code> (yarn dlx = npx) 를 실행하여 관련 세팅을 포함한 <code>.vscode</code> 폴더를 생성합니다.</p>
  1591.  
  1592.  
  1593.  
  1594. <pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  1595.  "recommendations": [
  1596.    "arcanis.vscode-zipfs",
  1597.    "dbaeumer.vscode-eslint",
  1598.    "esbenp.prettier-vscode"
  1599.  ]
  1600. }</pre>
  1601.  
  1602.  
  1603.  
  1604. <pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  1605.  "search.exclude": {
  1606.    "**/.yarn": true,
  1607.    "**/.pnp.*": true
  1608.  },
  1609.  "eslint.nodePath": ".yarn/sdks",
  1610.  "prettier.prettierPath": ".yarn/sdks/prettier/index.js",
  1611.  "typescript.tsdk": ".yarn/sdks/typescript/lib",
  1612.  "typescript.enablePromptUseWorkspaceTsdk": true
  1613. }</pre>
  1614.  
  1615.  
  1616.  
  1617. <p>4. 설치가 완료되면 아무 타입스크립트 파일이나 들어간 다음</p>
  1618.  
  1619.  
  1620.  
  1621. <p>5. 우측 하단 TypeScript 클릭 or <code>cmd + shift + p</code> 를 눌러 TypeScript 검색</p>
  1622.  
  1623.  
  1624.  
  1625. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242264-c9d267c6-a43f-427e-951d-9d0bdd166f42.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1626.  
  1627.  
  1628.  
  1629. <p>6. Use Workspace Version 클릭</p>
  1630.  
  1631.  
  1632.  
  1633. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242269-6d5640db-1ed4-46f1-9242-d4ae20642188.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1634.  
  1635.  
  1636.  
  1637. <p>여기까지 진행 한 뒤 다시 한번 진행 상황 저장을 위해 커밋합니다.</p>
  1638.  
  1639.  
  1640.  
  1641. <h3>5) Dockerfile 수정</h3>
  1642.  
  1643.  
  1644.  
  1645. <p>이상 로컬에서 필요한 작업들은 모두 완료를 해주었습니다. 배포 시 도커를 사용하고 있으므로 <code>Dockerfile</code> 에도 필요한 작업을 해줍니다. 아래와 같이 작업을 해주었으며 필요한 설명은 파일 내 주석으로 추가해두었습니다.</p>
  1646.  
  1647.  
  1648.  
  1649. <p>세 가지 정도의 주의사항이 있습니다. 하나는 <code>yarn berry</code> 가 <code>Node 16.14+</code> 버전에서 동작한다는 것이고, 다른 하나는 <code>yarn berry</code> 에서 <code>zero install</code> 을 사용할 때 <code>yarn install</code> 시 <code>--immutable</code> 옵션을 사용해야 하고, Docker로 배포 시 Dockerfile에 다음과 같이 작성하여 관련 파일들을 working directory에 복사해줘야 합니다.</p>
  1650.  
  1651.  
  1652.  
  1653. <pre class="wp-block-code"><code>COPY package* yarn.lock .pnp*     ./
  1654. COPY .yarnrc.yml                  ./
  1655. COPY .yarn                        ./.yarn</code></pre>
  1656.  
  1657.  
  1658.  
  1659. <p>위와 같은 과정을 거치면 yarn berry의 zero install을 사용할 수 있게 됩니다. 개선된 빌드 시간은 프로젝트마다 차이가 있으나 지금까지 적용해본 케이스들에서는 약 50초 ~ 1분 정도의 시간 단축이 있었습니다.</p>
  1660.  
  1661.  
  1662.  
  1663. <h2>4. 트러블 슈팅 (with Github issues)</h2>
  1664.  
  1665.  
  1666.  
  1667. <p><code>yarn berry</code> 가 처음 발표되었을 때에 비해 관련 자료도 많아지고, <a href="https://yarnpkg.com/features/pnp#compatibility-table" target="_blank" rel="noreferrer noopener">여러 대규모 프로젝트</a>에서 지원하기 시작하는 등 꾸준한 개선이 있어왔지만, 기존 패키지 매니저와의 구조적인 차이 때문에 맞닥뜨리게 되는 낯선 이슈들이 여전히 존재합니다. 이번 섹션에서는 그러한 문제들을 해결했던 경험을 이야기해보겠습니다.</p>
  1668.  
  1669.  
  1670.  
  1671. <h3>1) 커밋에 포함되지 않는 종속성 문제</h3>
  1672.  
  1673.  
  1674.  
  1675. <p><code>yarn install</code> 시 커밋에 포함되지 않는 파일들이 있습니다. <code>.yarn/install-state.gz</code> 같은 경우 최적화 관련 파일이기 때문에 애초에 커밋할 필요 없다고 공식 문서에서 안내하고 있습니다.</p>
  1676.  
  1677.  
  1678.  
  1679. <p>한편 예상치 못한 예외 케이스도 있었습니다. Next.js 등에 포함되는 `swc`의 경우 운영체제에 종속되는 부분이 있다보니 커밋에 포함시킬 경우 실행환경에 따라 문제를 일으킬 수 있어 커밋에서 제외되고 있습니다. 따라서 swc를 사용한다면 정상적인 빌드를 위해 최초 1회 설치 명령어가 필요합니다.</p>
  1680.  
  1681.  
  1682.  
  1683. <p>만약 설치를 실행하지 않으면 아래와 같은 오류가 발생합니다.</p>
  1684.  
  1685.  
  1686.  
  1687. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242557-6ceaf60b-7044-42e1-99ac-e975823d0088.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1688.  
  1689.  
  1690.  
  1691. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242563-29edb728-b040-402d-bcdb-dcf90a104a80.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1692.  
  1693.  
  1694.  
  1695. <p>설치 후 추가된 파일들이 .gitignore에 등록되어 있으며, 설치된 종속성의 폴더명으로부터 플랫폼 종속적이라는 사실을 추측해볼 수 있습니다. 참고로 <code>.yarn/unplugged</code> 는 zip으로 묶이지 않고 압축해제 된 종속성들이 설치되는 경로입니다. <code>yarn unplug</code> 등의 명령어를 사용하면 압축된 종속성 들을 풀어서 확인할 수 있습니다.</p>
  1696.  
  1697.  
  1698.  
  1699. <h3>2) ESLint import/order 관련 이슈</h3>
  1700.  
  1701.  
  1702.  
  1703. <p><code>eslint</code> 에서 import 관련 룰을 사용하고 있다면 추가 세팅이 필요합니다. <code>eslint-plugin-import</code> 에서 제공하는 <code>import/order</code> 옵션을 활용해 다음과 같이 외부 의존성과 내부 의존성을 구분지어 줄바꿈 해주고 있었습니다.</p>
  1704.  
  1705.  
  1706.  
  1707. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242568-de643261-f829-4f7a-a5c3-ebff19da0a53.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1708.  
  1709.  
  1710.  
  1711. <p>이 Lint 규칙이 yarn berry 적용 후 제대로 작동하지 않는 것을 발견하였습니다. 프로젝트 내부에서 가져온 모듈과, 외부 라이브러리에서 가져오는 모듈을 구분하는 기준이 node_modules가 경로에 포함되어 있는지 여부였을 것이라 생각하여 검색해보았습니다. <a href="https://github.com/import-js/eslint-plugin-import/issues/2164" target="_blank" rel="noreferrer noopener">관련 이슈</a>로부터 힌트를 얻어 <a href="https://github.com/import-js/eslint-plugin-import#importexternal-module-folders" target="_blank" rel="noreferrer noopener">README</a> 내에 언급된 해결책을 찾을 수 있었습니다.</p>
  1712.  
  1713.  
  1714.  
  1715. <blockquote class="wp-block-quote"><p><em>If you are using yarn PnP as your package manager, add the .yarn folder and all your installed dependencies will be considered as external, instead of internal.</em></p></blockquote>
  1716.  
  1717.  
  1718.  
  1719. <p>이 문제를 해결하려면 <code>.eslintrc.js</code> 에 다음과 같이 옵션을 추가하여 <code>.yarn</code> 경로를 외부 의존성으로 인식시켜주면 됩니다.</p>
  1720.  
  1721.  
  1722.  
  1723. <pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// .eslintrc.js
  1724. // ...
  1725.  settings: {
  1726.    'import/external-module-folders': ['.yarn'],
  1727. // ...</pre>
  1728.  
  1729.  
  1730.  
  1731. <h3>3) yarn berry에서 pre-hook 지원하지 않음</h3>
  1732.  
  1733.  
  1734.  
  1735. <p>yarn 2.x 버전 부터는 pre-hook(ex. <code>preinstall</code> , <code>prepare</code> 등) 을 지원하지 않습니다. <a href="https://yarnpkg.com/advanced/lifecycle-scripts#gatsby-focus-wrapper" target="_blank" rel="noreferrer noopener">문서</a>에 따르면 이는 사이드 이펙트를 줄이기 위한 의도적인 변경이라고 하며, 호환성을 위해서 <code>preinstall</code> 과 <code>install</code> 은 <code>postinstall</code>의 일부로서 실행됩니다.</p>
  1736.  
  1737.  
  1738.  
  1739. <p>기존에 husky 등을 사용하기 위해 걸어둔 pre-hook이 있었다면 yarn berry 업그레이드 후 작동하지 않을 것이므로 이에 대한 처리가 필요합니다.</p>
  1740.  
  1741.  
  1742.  
  1743. <pre class="wp-block-code"><code>"postinstall": "husky install"</code></pre>
  1744.  
  1745.  
  1746.  
  1747. <h3>4) yarn berry와 vite를 함께 사용할 때 storybook이 실행되지 않는 문제</h3>
  1748.  
  1749.  
  1750.  
  1751. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242682-106bffb8-6eb7-452a-86f1-869726aa4b17.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1752.  
  1753.  
  1754.  
  1755. <p>이 경우는 누락된 devDependencies를 다 깔아주면 되는 문제로 간단하게 해결할 수 있었습니다. 관련 이슈는 <a href="https://github.com/storybookjs/builder-vite/issues/141" target="_blank" rel="noreferrer noopener">여기</a>에서 찾아볼 수 있습니다.</p>
  1756.  
  1757.  
  1758.  
  1759. <p>하지만 이 종속성들을 설치하고 나서도 storybook이 정상적으로 실행되지는 않았는데, 스토리북으로 띄운 화면 상의 콘솔에 `&#8221;Cannot access &#8220;./util.inspect.custom&#8221; in client code.&#8221;` 라는 에러가 발생했습니다. pnp와 vite 사이에서만 발생하는 문제로 build 과정에서 서버 / 클라이언트 환경에서 실행되는 코드들이 적절히 처리되지 않아서 생기는 문제로 이해했습니다. vite 측에서 폴리필을 추가하여 해결한 것으로 보이며, 관련 이슈는 <a href="https://github.com/vitejs/vite/issues/9238" target="_blank" rel="noreferrer noopener">여기</a>, <a href="https://github.com/vitejs/vite/issues/7576" target="_blank" rel="noreferrer noopener">여기2</a>에서 찾아볼 수 있습니다.</p>
  1760.  
  1761.  
  1762.  
  1763. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242692-31961169-1beb-4de4-9d3a-a564b61c0ed4.png?ssl=1" alt="" data-recalc-dims="1"/></figure></div>
  1764.  
  1765.  
  1766.  
  1767. <p>이 외에도 vite와의 조합에서 생기는 문제는 또 있었는데요. build를 실행했을 시 종속성을 제대로 찾지 못하는 문제였습니다. 이 문제는 yarn berry를 3.3.0으로 올리고 vscode sdk를 재설치한 뒤, vite를 3.2.0 버전으로 업데이트 하여 해결했습니다. 관련 이슈는 <a href="https://github.com/yarnpkg/berry/issues/4872#issuecomment-1284318301" target="_blank" rel="noreferrer noopener">여기</a>에서 찾아볼 수 있습니다.</p>
  1768.  
  1769.  
  1770.  
  1771. <h2>5. 개선 결과</h2>
  1772.  
  1773.  
  1774.  
  1775. <p>결과적으로 개선된 빌드 시간은 프로젝트마다 차이가 있으나 지금까지 적용해본 케이스들에서는 yarn berry 단독으로만 따졌을 때 평균적으로 약 50초 ~ 1분 정도의 시간 단축이 있었습니다. 만약 앞서 언급한 swc 관련 설치 시간을 생략할 수 있다면 20초 정도를 추가로 단축할 여지가 있습니다.</p>
  1776.  
  1777.  
  1778.  
  1779. <figure class="wp-block-image"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/220504822-90f3f3a5-4142-4bdb-bd5e-32e8b682f2c8.png?ssl=1" alt="image" data-recalc-dims="1"/><figcaption>swc 설치에 소요되는 시간</figcaption></figure>
  1780.  
  1781.  
  1782.  
  1783. <p>빌드 시간 단축 이외에도 실제 도입해보고 나서 체감할 수 있었던 장점들이 많았습니다. 레포지토리 설치 시 종속성 크기 감소, 로컬과 리모트 환경에서의 빌드 결과물의 동일성 보장, 엄격한 종속성 트리 관리로 인한 안정성 향상 등의 이점이 기존 버전 대비 방법론적인 개선을 이룰 수 있었습니다.</p>
  1784.  
  1785.  
  1786.  
  1787. <p>개발 단계에서 git branch 변경 시 반복적으로 install 스크립트를 실행하여 node_modules를 업데이트 해줘야 하거나, 종종 잘못 설치된 종속성 때문에 한참 디버깅을 하다 결국 node_modules를 지우고 재설치 해야 하는 번거로움이 줄어든 것도 체감되는 부분이었습니다.</p>
  1788.  
  1789.  
  1790.  
  1791. <p>추가로 Dockerfile에 들어있던 세팅에서 불필요한 부분을 걷어내고, <a href="https://docs.aws.amazon.com/ko_kr/codebuild/latest/userguide/build-caching.html#caching-local">AWS Codebuild에서 Docker Layer가 로컬 캐싱</a>될 수 있는 방법을 찾아 적용하였습니다. yarn berry와는 직접적으로 관련은 없지만 배포 성능을 개선하는 도중에 진행했던 변경이라 함께 언급해두겠습니다.</p>
  1792.  
  1793.  
  1794.  
  1795. <p>도커 파일 내 각 레이어는 변경사항이 생기지 않는 이상 새롭게 생성될 필요가 없습니다. 변경이 사항 없을 시 CodeBuild의 빌드 호스트가 자연스럽게 Docker Layer 캐싱을 이용할 수 있도록 세팅을 변경해주었습니다.</p>
  1796.  
  1797.  
  1798.  
  1799. <p>현재 AWS CodePipeline을 사용하여 배포하고 있으며, 빌드는 AWS Codebuild를 사용하고 있으므로, 해당 단계에서 생성된 빌드 결과물을 캐싱에 사용할 수 있도록 아래와 같이 체크해줍니다. 다만 이 로컬 캐시의 정확한 유효 시간(약 5 ~ 15분)이나 히트 조건에 대해서는 조금 더 확인이 필요합니다. (<a href="https://stackoverflow.com/questions/58793704/aws-codebuild-local-cache-failing-to-actually-cache">링크</a>)</p>
  1800.  
  1801.  
  1802.  
  1803. <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/215242409-a7761e7b-6c11-44e1-9371-c22e10085819.png?ssl=1" alt="" data-recalc-dims="1"/><figcaption>AWS Codebuild &#8211; 편집 &#8211; 아티팩트 &#8211; 캐싱 메뉴 하단</figcaption></figure></div>
  1804.  
  1805.  
  1806.  
  1807. <p>이 과정에서 기존에 잘못 세팅되어 있던 Codebuild의 Buildspec을 바로 잡고 로컬 캐싱이 작동하도록 함으로서 추가적으로 빌드 시간을 단축하였습니다. Next.js 기반의 어드민 프로젝트 기준 최대 2분 가량 추가 단축한 것으로 추정됩니다.</p>
  1808.  
  1809.  
  1810.  
  1811. <div class="wp-block-image"><figure class="aligncenter"><img src="https://i0.wp.com/user-images.githubusercontent.com/35240142/220504970-ba4c5fb9-d6ad-4510-85ec-6785ac8b7132.png?ssl=1" alt="image" data-recalc-dims="1"/><figcaption>캐시 히트 시 빌드 소요 시간 2분 37초 (직전 빌드 4분 28초 &#8211; yarn berry 적용 분 포함)</figcaption></figure></div>
  1812.  
  1813.  
  1814.  
  1815. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?ssl=1"><img data-attachment-id="3557" data-permalink="https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/image-6-4/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?fit=2314%2C624&amp;ssl=1" data-orig-size="2314,624" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-6" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?fit=300%2C81&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?fit=1024%2C276&amp;ssl=1" loading="lazy" width="1024" height="276" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=1024%2C276&#038;ssl=1" alt="" class="wp-image-3557" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=1024%2C276&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=300%2C81&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=768%2C207&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=1536%2C414&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=2048%2C552&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=750%2C202&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image-6.png?resize=1140%2C307&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>도커 레이어 레벨에서 캐싱이 일어났을 때의 빌드 로그</figcaption></figure></div>
  1816.  
  1817.  
  1818.  
  1819. <p>한 프로젝트는 언급드린 두 가지 조치를 통하여 프로젝트에 따라 빌드 시간이 5분 30초 → 1분 50초로 드라마틱하게 감소하기도 했는데, 프로젝트별 인스턴스 세팅과 빌드 시점, 캐시 여부에 따라 개선되는 폭은 상이할 것으로 생각되어 절대적인 수치로는 참고하지 말아주시고 대략적인 수치로만 봐주시면 좋을 것 같습니다.</p>
  1820.  
  1821.  
  1822.  
  1823. <h2>6. 마치며</h2>
  1824.  
  1825.  
  1826.  
  1827. <p>한 명의 아이를 기르기 위해 온 마을이 필요하다는 말 처럼, 하나의 웹 서비스가 만들어지기 위해서는 정말 다양한 기술이 필요합니다. 어느 개발이나 그렇겠지만 특히 최근 자바스크립트 생태계는 특히 이런 <code>툴체인(Toolchain)</code> 의 조합을 여러 방향으로 실험해보는 활발한 분위기가 느껴집니다. <code>npm</code> 과 함께 오랫동안 사랑 받아온 패키지 매니저 <code>yarn</code> 또한 개발에 필요한 라이브러리들의 설치와 종속성을 담당하는 점에서 툴체인의 중요한 일부를 담당하고 있습니다.</p>
  1828.  
  1829.  
  1830.  
  1831. <p>그 중에서도 yarn berry와 pnp는 과감하면서도 멋진 진전이라고 생각합니다. 물론 위에 말씀드린 이슈들처럼 아직 사용자들이 직접 부딪혀야 하는 문제들이 산재해있지만, 기술이 처음 공개되었을 때와 비교하면 현재 이 리스크들은 감내할 수 있는 수준이라고 생각합니다. <code>yarn unplug</code> , <code>yarn why</code> , <code>yarn patch</code> 등의 기능을 활용하여 디버깅하고, 긴급한 상황에서는 <code>nodeLinker: node-modules</code> 로 되돌리거나 <code>pnpMode: loose</code> 등의 절충점이 존재하므로 자신 있게 도입해볼 수 있을 것 같습니다.</p>
  1832.  
  1833.  
  1834.  
  1835. <p>사실 <code>yarn berry</code> 를 도입하는 과정에서 가장 좋았던 점은 성능상의 이점보다도, yarn이나 여러 패키지 내부의 코드를 살펴보며 동작 원리를 가늠하거나, Github에 올라온 issue들을 싹싹 긁어가며 읽고, peerDependencies 등 종속성들 간의 관계를 생각하며 패키지를 이리저리 설치해보던 시간들이었습니다. 가벼운 마음으로 시작했지만 역시 어떤 기술이든 직접 만져보고 굴려볼 때 이해도가 더 높아진다는 사실을 새삼스레 곱씹어보게 됐던 것 같네요.</p>
  1836.  
  1837.  
  1838.  
  1839. <p>서두에서 말씀드렸듯 결국 저희 팀에서는 비록 <code>Turborepo</code> 와의 호환 이슈로 <code>pnpm</code> 을 선택하게 되었지만 yarn berry는 충분히 매력적인 기술인만큼 검토해보시고 도입을 적극 고려해보셨으면 좋겠습니다.</p>
  1840.  
  1841.  
  1842.  
  1843. <p>이제 저희 팀의 채용 홍보로 글을 마무리 짓도록 하겠습니다. <strong>리멤버 웹 파트에서는 이러한 기술적인 고민을 함께 나누며 성장하실 동료분을 모시고 있습니다.</strong> 서류 검토, 기술 면접, 컬처핏 면접 절차 세 단계로 간소하게 프로세스를 진행하고 있습니다. 보다 상세한 내용은 <a href="https://hello.remember.co.kr/recruit/web">채용 공고</a>를 확인 부탁드리며, 많은 관심과 지원 부탁드리겠습니다.</p>
  1844.  
  1845.  
  1846.  
  1847. <p>지금까지 긴 글 읽어주셔서 감사합니다.</p>
  1848.  
  1849.  
  1850.  
  1851. <div class="wp-container-1 wp-block-buttons alignwide">
  1852. <div class="wp-block-button aligncenter"><a class="wp-block-button__link has-luminous-vivid-orange-background-color has-background" href="https://hello.remember.co.kr/recruit/web" target="_blank" rel="noreferrer noopener">&gt;_ 웹 파트 채용공고 보러가기</a></div>
  1853. </div>
  1854.  
  1855.  
  1856.  
  1857. <p></p>
  1858.  
  1859.  
  1860.  
  1861. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?ssl=1"><img data-attachment-id="3548" data-permalink="https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/image-13/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?fit=2318%2C622&amp;ssl=1" data-orig-size="2318,622" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?fit=300%2C81&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?fit=1024%2C275&amp;ssl=1" loading="lazy" width="1024" height="275" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=1024%2C275&#038;ssl=1" alt="" class="wp-image-3548" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=1024%2C275&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=300%2C81&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=768%2C206&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=1536%2C412&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=2048%2C550&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=750%2C201&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2023/02/image.png?resize=1140%2C306&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>도입 초기에는 모든 에러로부터 Yarn Berry가 의심의 눈초리를 받을 수 있으니 주의 요망</figcaption></figure></div>
  1862.  
  1863.  
  1864.  
  1865. <h2>6. 참고 자료</h2>
  1866.  
  1867.  
  1868.  
  1869. <ul><li><a href="https://yarnpkg.com/" target="_blank" rel="noreferrer noopener">https://yarnpkg.com/</a></li><li><a href="https://toss.tech/article/node-modules-and-yarn-berry" target="_blank" rel="noreferrer noopener">node_modules로부터 우리를 구원해 줄 Yarn Berry</a></li><li><a href="https://medium.com/wantedjobs/yarn-berry-%EC%A0%81%EC%9A%A9%EA%B8%B0-1-e4347be5987" target="_blank" rel="noreferrer noopener">yarn berry 적용기(1)</a></li><li><a href="https://medium.com/teamo2/yarn-berry-%EA%B5%B3%EC%9D%B4-%EB%8F%84%EC%9E%85%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C-d6221b9beca6" target="_blank" rel="noreferrer noopener">Yarn Berry, 굳이 도입해야 할까?</a></li><li><a href="https://yceffort.kr/2022/05/npm-vs-yarn-vs-pnpm" target="_blank" rel="noreferrer noopener">npm, yarn, pnpm 비교해보기</a></li></ul>
  1870. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/">리멤버 웹 서비스 좌충우돌 Yarn Berry 도입기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1871. ]]></content:encoded>
  1872. <wfw:commentRss>https://blog.dramancompany.com/2023/02/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a2%8c%ec%b6%a9%ec%9a%b0%eb%8f%8c-yarn-berry-%eb%8f%84%ec%9e%85%ea%b8%b0/feed/</wfw:commentRss>
  1873. <slash:comments>5</slash:comments>
  1874. <post-id xmlns="com-wordpress:feed-additions:1">3445</post-id> </item>
  1875. <item>
  1876. <title>AI 명함촬영인식 &#8216;리오(RIO)&#8217; 적용기 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기</title>
  1877. <link>https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4-%ec%a0%81%ec%9a%a9%ea%b8%b0-2%eb%b6%80-ml-model-converter%ec%99%80-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c/</link>
  1878. <comments>https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4-%ec%a0%81%ec%9a%a9%ea%b8%b0-2%eb%b6%80-ml-model-converter%ec%99%80-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c/#comments</comments>
  1879. <dc:creator><![CDATA[민석 강]]></dc:creator>
  1880. <pubDate>Wed, 23 Nov 2022 01:16:40 +0000</pubDate>
  1881. <category><![CDATA[AI Lab.]]></category>
  1882. <category><![CDATA[AI 명함 촬영 인식]]></category>
  1883. <category><![CDATA[Client-Side Computing]]></category>
  1884. <category><![CDATA[Edge Computing]]></category>
  1885. <category><![CDATA[Intermediate Representation]]></category>
  1886. <category><![CDATA[ML Model Converter]]></category>
  1887. <category><![CDATA[rio]]></category>
  1888. <category><![CDATA[Tensorflow Lite]]></category>
  1889. <category><![CDATA[리오]]></category>
  1890. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3447</guid>
  1891.  
  1892. <description><![CDATA[<p>AI 명함 촬영 인식 ‘리오(RIO)’의 모델을 Client-Side Computing로 적용하기 위한 다양한 시행착오들을 공유하고자 합니다. 학습된 PyTorch Model을 ONNX와 Tensorflow 모델을 거쳐 TF Lite Model로의 변환과정과 모델 추론 안드로이드 샘플 환경에서의 테스트까지 내용을 소개 하고자 합니다.</p>
  1893. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4-%ec%a0%81%ec%9a%a9%ea%b8%b0-2%eb%b6%80-ml-model-converter%ec%99%80-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c/">AI 명함촬영인식 &#8216;리오(RIO)&#8217; 적용기 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1894. ]]></description>
  1895. <content:encoded><![CDATA[
  1896. <p></p>
  1897.  
  1898.  
  1899.  
  1900. <p class="has-medium-font-size">안녕하세요. 빅데이터센터 AI Lab 강민석입니다.</p>
  1901.  
  1902.  
  1903.  
  1904. <p class="has-medium-font-size">이번 <strong>AI 명함 촬영 인식 ‘리오(RIO)’ </strong>적용기 2부에서는 리멤버 앱에 AI 명함 촬영 인식 ‘리오(RIO)’의 모델을 Client-Side Computing로 적용하기 위한 다양한 시행착오들을 공유하고자 합니다. 학습된 PyTorch Model을 ONNX와 Tensorflow 모델을 거쳐 TF Lite Model로의 변환과정과 모델 추론 안드로이드 샘플 환경에서의 테스트까지 내용을 소개 하고자 합니다. 이 글에서 AI 명함 촬영 인식 ‘리오(RIO)’ 적용을 위해 최종적으로 진행된 <strong>ML 모델의 변환 방법</strong>과 <strong>모델 추론을 위한 안드로이드 테스트 환경</strong>에 대해 설명 드리고자 합니다.</p>
  1905.  
  1906.  
  1907.  
  1908. <p class="has-medium-font-size">이 AI 명함 촬영 인식 ‘리오’ 적용기 포스팅은 1부와 2부로 나누어 포스팅 되어 있습니다. 이번 AI 명함 촬영 인식 ‘리오’ 적용기 2부에서는 ML Model Converter와 안드로이드 앱 적용기에 대해 작성 되어있습니다.</p>
  1909.  
  1910.  
  1911.  
  1912. <ul class="has-medium-font-size"><li><strong>AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부 &#8211; 명함 촬영 인식 위한 Instance Segmentation &amp; Computer Vision</strong></li></ul>
  1913.  
  1914.  
  1915.  
  1916. <ul class="has-medium-font-size"><li><strong>AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기</strong></li></ul>
  1917.  
  1918.  
  1919.  
  1920. <div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>
  1921.  
  1922.  
  1923.  
  1924. <h2><strong>Client-Side Computing (또는 Edge Computing)</strong></h2>
  1925.  
  1926.  
  1927.  
  1928. <p class="has-medium-font-size"><strong>Client-Side Computing</strong>은 데이터를 클라우드 서버로 보내는 대신 로컬 기기에서 처리하는 것입니다. 기계 학습과 관련하여 Client-Side Computing은 장치에서 추론이 직접 수행하는 것을 의미합니다. AI 명함 촬영 인식 ‘리오(RIO)’가 Client-Side Computing 사용 해야 하는 데에는 4가지 주된 이유가 있습니다.</p>
  1929.  
  1930.  
  1931.  
  1932. <ol class="has-medium-font-size"><li><strong>실시간 추론</strong> : 리멤버 앱이 동작하는 모바일 장치의 ML 모델 추론 계산은 네트워크를 통해 API 결과를 기다리는 것보다 빠릅니다. 실시간으로 사용자에게 명함의 위치를 보여주고 명함의 영역을 잘라내 제공합니다.</li><li><strong>오프라인 기능</strong> : Client-Side Computing은 인터넷 연결 없이도 명함이 촬영되는 순간부터 명함의 위치와 명함의 영역 잘라서 명함의 이미지만을 제공하게 됩니다.</li><li><strong>데이터 프라이버시</strong> : 인터넷을 통해 전송되거나 클라우드 데이터베이스에 추가로 저장되는 위험을 낮춰 줍니다.</li><li><strong>비용 절감</strong> : ML 서버가 필요하지 않으므로 서버 비용이 절감됩니다. 이 외에도 명함 이미지가 서버로 전송되지 않기 때문에 데이터 전송 네트워크 비용이 절감됩니다.</li></ol>
  1933.  
  1934.  
  1935.  
  1936. <p class="has-medium-font-size">Client-Side Computing의 경우 큰 장점들이 있지만 다양한 제약 사항들이 생기게 됩니다. 모바일 기기의 처리능력의 제한, 모델 크기(용량)에 대한 제한, 모바일 적용을 위한 ML 프레임워크의 의존성에 대한 제약 사항들이 생기게 되고 이를 해결 하려는 다양한 리서치를 진행 하게 되었습니다. 이 과정에서 생긴 시행착오와 다양한 고민을 공유하여 관련 연구자 또는 개발자들의 시간을 절약하게 되었으면 좋겠습니다.</p>
  1937.  
  1938.  
  1939.  
  1940. <div style="height:73px" aria-hidden="true" class="wp-block-spacer"></div>
  1941.  
  1942.  
  1943.  
  1944. <h1><strong>ML Model Converter</strong></h1>
  1945.  
  1946.  
  1947.  
  1948. <p class="has-medium-font-size">학습된 ML 모델을 모바일과 같은 사용자의 장치에서 적용하기 위해서는 지연 시간, 개인 정보 보호, 다양한 기기와의 연결성, 모델의 크기, 전력 소비 등을 고려해야 한다는 문제가 존재합니다. 저희는 Pytorch Model을 TF Lite Model로 최종 모델로 변환하기로 하였는데, 그 이유는 산업과 관련된 제한 사항과 요구 사항에 대해 오랜 기간 긴밀히 발전해오고 있는 Tensorflow Lite의 안정성과 Arm CPU 연산에 최적화된 더 많은 사례가 있으므로 타 프레임워크 환경들과 비교하여 더 나은 성능을 쉽고 빠르게 적용 가능 하다고 판단했습니다.</p>
  1949.  
  1950.  
  1951.  
  1952. <p class="has-medium-font-size">아래의 글에서 Pytorch Model을 TF Lite Model로 변환하는 과정을 설명하고자 합니다. 변환 과정은 <strong>PyTorch Model → ONNX Graph(+TorchScript)→ Tensorflow Model → TF Lite Model</strong> 순으로 진행하였습니다. 관련 기술을 소개하고 변환하는 방법에 대해 설명해 드리도록 하겠습니다.</p>
  1953.  
  1954.  
  1955.  
  1956. <div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>
  1957.  
  1958.  
  1959.  
  1960. <h2><strong>PyTorch Model을 ONNX Graph(+TorchScript)로의 변환</strong></h2>
  1961.  
  1962.  
  1963.  
  1964. <p class="has-medium-font-size">최종 모델인 Tensorflow Lite 모델로 변환하기 위해서는 중간 과정에 Tensorflow 모델로 변환이 필요한데, Pytorch Model을 직접 Tensorflow 모델로 변환하는 기능이 제공되어 있지 않습니다. 그래서 먼저 상호 운용가능한 ONNX 그래프로 변환을 하게 됩니다. PyTorch에서 제공되는 ONNX 그래프로 변환하는 <strong><code>torch.onnx.export()</code> </strong>함수를 통해 PyTorch 모델을 ONNX*로 변환하였습니다.</p>
  1965.  
  1966.  
  1967.  
  1968. <figure class="wp-block-pullquote"><blockquote><p><strong>ONNX</strong>는 Open Neural Network Exchange의 줄인 말로서 이름과 같이 다른 ML 프레임워크 환경(Tensorflow, PyTorch 등)에서 만들어진 모델들을 서로 호환될 수 있도록 만들어진 공유 플랫폼입니다.</p></blockquote></figure>
  1969.  
  1970.  
  1971.  
  1972. <p class="has-text-align-center"><img data-attachment-id="3436" data-permalink="https://blog.dramancompany.com/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-1-torchscript%e1%84%8b%e1%85%b4-script-mode-%e1%84%87%e1%85%a7%e1%86%ab%e1%84%92%e1%85%aa%e1%86%ab/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?fit=2000%2C871&amp;ssl=1" data-orig-size="2000,871" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 1. TorchScript의 Script Mode 변환" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?fit=300%2C131&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?fit=1024%2C446&amp;ssl=1" loading="lazy" width="2000" height="871" class="wp-image-3436" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=2000%2C871&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=300%2C131&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=1024%2C446&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=768%2C334&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=1536%2C669&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=750%2C327&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-TorchScript의-Script-Mode-변환.png?resize=1140%2C496&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  1973.  
  1974.  
  1975.  
  1976. <p class="has-text-align-center">그림 1. TorchScript의 Script Mode 변환[1]</p>
  1977.  
  1978.  
  1979.  
  1980. <p class="has-medium-font-size"><code><strong>torch.onnx.export()</strong></code> 함수의 실제 동작은 내부적으로 TorchScript를 통해 코드를 Eager Mode에서 Script Mode로 변환하여 중간 표현(Intermediate Representation, IR)* 그래프를 ONNX 그래프로 변환하기 전에 생성하게 됩니다. 그 이후에 Pytorch의 Script Mode의 중간 표현(IR)*을 ONNX 그래프로 변환하여 반환하게 됩니다.</p>
  1981.  
  1982.  
  1983.  
  1984. <figure class="wp-block-pullquote has-text-align-center"><blockquote><p><strong>중간표현(Intermediate Representation, IR)</strong>은 소스 코드를 나타내기 위해 컴파일러 또는 가상 머신에서 내부적으로 사용하는 데이터 구조 또는 코드입니다. IR은 최적화 및 모델 변환과 같은 추가적인 처리 과정에 도움이 되도록 설계되어 있습니다.</p></blockquote></figure>
  1985.  
  1986.  
  1987.  
  1988. <p class="has-text-align-center"><img data-attachment-id="3437" data-permalink="https://blog.dramancompany.com/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-2-onnx%e1%84%8b%e1%85%b4-%e1%84%89%e1%85%a1%e1%86%bc%e1%84%92%e1%85%a9-%e1%84%8b%e1%85%ae%e1%86%ab%e1%84%8b%e1%85%ad%e1%86%bc%e1%84%89%e1%85%a5%e1%86%bc/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?fit=2000%2C1640&amp;ssl=1" data-orig-size="2000,1640" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 2. ONNX의 상호 운용성 [2]" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?fit=300%2C246&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?fit=1024%2C840&amp;ssl=1" loading="lazy" width="2000" height="1640" class="wp-image-3437" style="width: 700px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=2000%2C1640&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=300%2C246&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=1024%2C840&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=768%2C630&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=1536%2C1260&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=750%2C615&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-ONNX의-상호-운용성-2.png?resize=1140%2C935&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  1989.  
  1990.  
  1991.  
  1992. <p class="has-text-align-center">그림 2. ONNX의 상호 운용성 [2]</p>
  1993.  
  1994.  
  1995.  
  1996. <p class="has-medium-font-size">ONNX 그래프로 모델 표현 하게 되면 다른 프레임 워크로 모델 표현(Framework Interoperability)이 가능한 것 뿐만 아니라, 이 과정에서 ONNX에서 제공되는 것 이외에도 최적화된 구조의 그래프 표현이 유지된 상태(Shared Optimization)로 변환될 수 있다는 이점이 있습니다. 이 과정에서 산업영역의 여러 하드웨어와 ML 컴파일러에 대한 다양한 선택지를 제공 받았던 것 같습니다.</p>
  1997.  
  1998.  
  1999.  
  2000. <div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>
  2001.  
  2002.  
  2003.  
  2004. <h2><strong>ONNX Graph를 Tensorflow Lite model로의 변환</strong></h2>
  2005.  
  2006.  
  2007.  
  2008. <p class="has-medium-font-size">ONNX Graph를 Tensorflow Lite model(.tflite 파일 확장자로 식별되는 최적화된 FlatBuffer 형식)로 변환하기 위해서는 중간 과정으로 Tensorflow Model로의 변환이 필요합니다. 이를 위해서 ONNX를 위한 Tensorflow 백엔드 onnx-tensorflow[3]에서 제공되는 <code><strong>onnx_tf.backend.prepare(onnx_model)</strong></code> 함수를 사용하여 ONNX Graph를 Tensorflow 모델로 변환해줍니다. 그 이후에 TensorFlow Lite*[4]에서 제공되는 <code><strong>tf.lite.TFLiteConverter.from_saved_model(tf_model_path)</strong></code> 함수를 사용하여 Tensorflow 모델을 Tensorflow Lite model로 변환해주는 작업을 진행합니다.</p>
  2009.  
  2010.  
  2011.  
  2012. <figure class="wp-block-pullquote has-text-align-center"><blockquote><p><strong>TensorFlow Lite</strong>는 Android&nbsp;및&nbsp;iOS, 내장형 Linux&nbsp;및&nbsp;마이크로 컨트롤러&nbsp;등의 기기에서 모델을 실행할 수 있는 기능을 제공하기 위해 On-device에서 ML을 위한 해석기(Interpreter)와 라이브러리를 지원하는 프레임워크 입니다.</p></blockquote></figure>
  2013.  
  2014.  
  2015.  
  2016. <p class="has-text-align-center"><img data-attachment-id="3438" data-permalink="https://blog.dramancompany.com/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-3-%e1%84%86%e1%85%a9%e1%84%83%e1%85%a6%e1%86%af-%e1%84%87%e1%85%a7%e1%86%ab%e1%84%92%e1%85%aa%e1%86%ab%e1%84%8b%e1%85%b3%e1%86%af-%e1%84%8b%e1%85%b1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?fit=2000%2C1982&amp;ssl=1" data-orig-size="2000,1982" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림-3.-모델-변환을-위한-high-level-workflow4" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?fit=300%2C297&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?fit=1024%2C1015&amp;ssl=1" loading="lazy" width="2000" height="1982" class="wp-image-3438" style="width: 600px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=2000%2C1982&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=300%2C297&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=1024%2C1015&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=150%2C150&amp;ssl=1 150w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=768%2C761&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=1536%2C1522&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=75%2C75&amp;ssl=1 75w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=750%2C743&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3.-모델-변환을-위한-high-level-workflow4.png?resize=1140%2C1130&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2017.  
  2018.  
  2019.  
  2020. <p class="has-text-align-center">그림 3. 모델 변환을 위한 high-level workflow[4]</p>
  2021.  
  2022.  
  2023.  
  2024. <p class="has-medium-font-size">Pytorch Model을 TF Lite Model로의 변환 과정을 코드로 보면 20줄 내외의 간단한 API 호출 몇 줄로 표현되지만, 내부적인 동작에 대해 상세하게 설명해 보았습니다. Quantization을 추가로 실험하였지만 정확도가 다소 떨어지는 경향이 있었습니다. 아래의 표에서는 모델의 크기를 단순 비교한 테이블입니다. 각 모델에 대한 속도에 대한 비교는 각각 목표 하드웨어에 따라 최적화 방법이 달라 비교하지 않고 Quantization을 제외한 모든 비교 모델에서의 정확도 차이가 크게 나타나지 않아 표기하지 않았습니다.</p>
  2025.  
  2026.  
  2027.  
  2028. <p class="has-text-align-center"><img data-attachment-id="3440" data-permalink="https://blog.dramancompany.com/%e1%84%91%e1%85%ad1-%e1%84%86%e1%85%a9%e1%84%83%e1%85%a6%e1%86%af-%e1%84%91%e1%85%ad%e1%84%92%e1%85%a7%e1%86%ab-%e1%84%87%e1%85%a1%e1%86%bc%e1%84%87%e1%85%a5%e1%86%b8%e1%84%8b%e1%85%a6-%e1%84%84/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?fit=2000%2C209&amp;ssl=1" data-orig-size="2000,209" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="표1.-모델-표현-방법에-따른-모델-사이즈-비교" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?fit=300%2C31&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?fit=1024%2C107&amp;ssl=1" loading="lazy" width="2000" height="209" class="wp-image-3440" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=2000%2C209&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=300%2C31&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=1024%2C107&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=768%2C80&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=1536%2C161&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=750%2C78&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/표1.-모델-표현-방법에-따른-모델-사이즈-비교.png?resize=1140%2C119&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2029.  
  2030.  
  2031.  
  2032. <p class="has-text-align-center">표 1. 모델 표현 방법에 따른 모델 사이즈 비교</p>
  2033.  
  2034.  
  2035.  
  2036. <div style="height:73px" aria-hidden="true" class="wp-block-spacer"></div>
  2037.  
  2038.  
  2039.  
  2040. <h1><strong>모델 추론을 위한 안드로이드 테스트</strong> <strong>데모</strong> <strong>앱</strong></h1>
  2041.  
  2042.  
  2043.  
  2044. <h2><strong>On-deivce 모델 추론을 위한 Tensorflow Lite Interpreter</strong></h2>
  2045.  
  2046.  
  2047.  
  2048. <p class="has-text-align-center"><img data-attachment-id="3441" data-permalink="https://blog.dramancompany.com/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-4-on-device%e1%84%8b%e1%85%a6%e1%84%89%e1%85%a5%e1%84%8b%e1%85%b4-tensorflow-lite%e1%84%85%e1%85%b3%e1%86%af-%e1%84%89%e1%85%a1%e1%84%8b%e1%85%ad/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?fit=2000%2C1163&amp;ssl=1" data-orig-size="2000,1163" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 4. On-device에서의 TensorFlow Lite를 사용하여 모델 배포 [5]" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?fit=300%2C174&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?fit=1024%2C595&amp;ssl=1" loading="lazy" width="2000" height="1163" class="wp-image-3441" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=2000%2C1163&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=300%2C174&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=1024%2C595&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=768%2C447&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=1536%2C893&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=750%2C436&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-On-device에서의-TensorFlow-Lite를-사용하여-모델-배포-5.png?resize=1140%2C663&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2049.  
  2050.  
  2051.  
  2052. <p class="has-text-align-center">그림 4. On-device에서의 TensorFlow Lite를 사용하여 모델 배포 [5]</p>
  2053.  
  2054.  
  2055.  
  2056. <p class="has-medium-font-size">위의 내용에서 AI 명함 촬영 인식 ‘리오(RIO)’를 Client-Side Computing에서 사용하기 위해 ML Model Converter에 관해 소개했습니다. 실제 모바일 기기에서 ‘리오(RIO)’ 모델의 추론을 진행하기 위해 Tensorflow Lite Interpreter를 활용하게 되는데 위의 그림 4와 같이 모바일 기기의 하드웨어를 사용하게 됩니다.</p>
  2057.  
  2058.  
  2059.  
  2060. <p class="has-text-align-center"><img data-attachment-id="3442" data-permalink="https://blog.dramancompany.com/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-5-tensorflow-lite%e1%84%8b%e1%85%b4-%e1%84%8b%e1%85%a1%e1%84%8f%e1%85%b5%e1%84%90%e1%85%a6%e1%86%a8%e1%84%8e%e1%85%a5-%e1%84%83%e1%85%b5%e1%84%8c/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?fit=2000%2C1895&amp;ssl=1" data-orig-size="2000,1895" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 5. TensorFlow Lite의 아키텍처 디자인 [6]" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?fit=300%2C284&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?fit=1024%2C970&amp;ssl=1" loading="lazy" width="2000" height="1895" class="wp-image-3442" style="width: 700px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=2000%2C1895&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=300%2C284&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=1024%2C970&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=768%2C728&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=1536%2C1455&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=750%2C711&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-TensorFlow-Lite의-아키텍처-디자인-6.png?resize=1140%2C1080&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2061.  
  2062.  
  2063.  
  2064. <p class="has-text-align-center">그림 5. TensorFlow Lite의 아키텍처 디자인 [6]</p>
  2065.  
  2066.  
  2067.  
  2068. <p class="has-medium-font-size">앱 내에서는 그림 5와 같이 Tensorflow Lite는 앱 내에서 추론 모델을 로드하고 인터프리터를 호출하는 C++ API , 주변의 Convenience Wrapper 역할을 하는 Android 앱용 Java API가 제공됩니다. Java API를 통해 모델을 호출하고 Tensorflow Lite 인터프리터를 사용하여 Tensorflow Lite 모델의 앱내 추론을 진행하게 됩니다.</p>
  2069.  
  2070.  
  2071.  
  2072. <div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>
  2073.  
  2074.  
  2075.  
  2076. <h2><strong>JNI과 OpenCV를 활용한 Post Processing</strong></h2>
  2077.  
  2078.  
  2079.  
  2080. <p class="has-medium-font-size">Tensorflow Lite Interpreter 모델 추론을 통해 얻게 된 결과는 아웃풋 차원 변환, NMS(Non-maximum Suppression), 다양한 후처리가 필요한 이전의 저차원의 피처 값들로 반환하게 되어 있습니다. 이를 처리하기 위해서는 Python 인터프리터의 사용 없이 자바에서 구현이 되어야 하는데 자바보다는 속도 측면의 이점이 있고 OpenCV 활용이 수월한 C++로 구현한 다음 JNI 통해 호출하도록 구현하였습니다.</p>
  2081.  
  2082.  
  2083.  
  2084. <p class="has-medium-font-size">다양한 차원 변환 함수와 NMS(Non-maximum Suppression)는 직접 구현하여 호출하도록 설계 하였고 AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부에서 설명된 Post Processing의 여러 함수는 OpenCV를 활용하여 구현하게 되었습니다.</p>
  2085.  
  2086.  
  2087.  
  2088. <div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>
  2089.  
  2090.  
  2091.  
  2092. <h2><strong>AI 명함 촬영 인식 ‘리오(RIO)’ 테스트용 데모 앱</strong></h2>
  2093.  
  2094.  
  2095.  
  2096. <p class="has-text-align-center"><img data-attachment-id="3456" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4-%ec%a0%81%ec%9a%a9%ea%b8%b0-2%eb%b6%80-ml-model-converter%ec%99%80-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-17-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-3-44-04/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?fit=1382%2C780&amp;ssl=1" data-orig-size="1382,780" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷 2022-11-17 오후 3.44.04" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?fit=300%2C169&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?fit=1024%2C578&amp;ssl=1" loading="lazy" width="1382" height="780" class="wp-image-3456" style="width: 700px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?resize=1382%2C780&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?w=1382&amp;ssl=1 1382w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?resize=1024%2C578&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?resize=768%2C433&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?resize=750%2C423&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-3.44.04.png?resize=1140%2C643&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2097.  
  2098.  
  2099.  
  2100. <p class="has-text-align-center">그림 6. AI 명함 촬영 인식 ‘리오(RIO)’ 테스트용 데모앱 그림</p>
  2101.  
  2102.  
  2103.  
  2104. <p class="has-text-align-center"><img data-attachment-id="3391" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/rio-%e1%84%85%e1%85%b5%e1%84%86%e1%85%a6%e1%86%b7%e1%84%87%e1%85%a5-%e1%84%8b%e1%85%a2%e1%86%b8-%e1%84%92%e1%85%ac%e1%84%8c%e1%85%a5%e1%86%ab/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/RIO-리멤버-앱-회전.gif?fit=640%2C262&amp;ssl=1" data-orig-size="640,262" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="RIO 리멤버 앱-회전" data-image-description="" data-image-caption="&lt;p&gt;RIO 리멤버 앱&lt;/p&gt;
  2105. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/RIO-리멤버-앱-회전.gif?fit=300%2C123&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/RIO-리멤버-앱-회전.gif?fit=640%2C262&amp;ssl=1" loading="lazy" width="640" height="262" class="wp-image-3391" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/RIO-리멤버-앱-회전.gif?resize=640%2C262&#038;ssl=1" alt="" data-recalc-dims="1"></p>
  2106.  
  2107.  
  2108.  
  2109. <p class="has-text-align-center">그림 7. AI 명함 촬영 인식 ‘리오(RIO)’ 배포 버전</p>
  2110.  
  2111.  
  2112.  
  2113. <p class="has-medium-font-size">AI 명함 촬영 인식 ‘리오(RIO)’를 안드로이드 앱에서 실험하기 위해 그림 6과 같이 테스트용 앱을 제작해 다양한 실험을 진행했습니다. 주로 안드로이드 앱에서의 모델 로드, 모델 추론, 다양한 후처리에 대한 동작 테스트를 진행하고 보다 다양한 환경에서 촬영해가며 리멤버 앱 사용자가 촬영할만한 상황을 연출하여 테스트를 진행했습니다. 이 과정에서 안드로이드 테스트용 앱 제작부터 실험 작업까지 동료분들의 많은 도움을 받아 진행하게 되었습니다.</p>
  2114.  
  2115.  
  2116.  
  2117. <div style="height:73px" aria-hidden="true" class="wp-block-spacer"></div>
  2118.  
  2119.  
  2120.  
  2121. <h1><strong>AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부~2부를 마치며</strong></h1>
  2122.  
  2123.  
  2124.  
  2125. <p class="has-medium-font-size">AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부 &#8211; 명함 촬영 인식 위한 Instance Segmentation &amp; Computer Vision을 거쳐, 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기까지 내용을 설명해 드렸습니다. AI 명함 촬영 인식 ‘리오(RIO)’ 를 개발하면서 다양한 기술을 실험하고 테스트해나가면서 많은 시행착오를 겪었던 것 같습니다. 일련의 과정을 해결해 나가는 데 있어서 리멤버의 동료가 지니고 있는 “고객 WOW를 위한 빠른 실행을 팀웍으로”의 리멤버 Way를 직접 느꼈던 프로젝트였습니다. 프로젝트 관련해 도움을 주신 많은 분들께 다시 한번 감사드립니다.</p>
  2126.  
  2127.  
  2128.  
  2129. <div style="height:73px" aria-hidden="true" class="wp-block-spacer"></div>
  2130.  
  2131.  
  2132.  
  2133. <h1><strong>Reference</strong></h1>
  2134.  
  2135.  
  2136.  
  2137. <p>[1] TorchScript — PyTorch documentation</p>
  2138.  
  2139.  
  2140.  
  2141. <p>[2] ONNX: Preventing Framework Lock in | Fernando López | Medium</p>
  2142.  
  2143.  
  2144.  
  2145. <p>[3] onnx/onnx-tensorflow: Tensorflow Backend for ONNX | github.com</p>
  2146.  
  2147.  
  2148.  
  2149. <p>[4] 모바일 및 에지 장치용 ML&nbsp;|&nbsp;TensorFlow Lite</p>
  2150.  
  2151.  
  2152.  
  2153. <p>[4] Convert TensorFlow models | TensorFlow Lite</p>
  2154.  
  2155.  
  2156.  
  2157. <p>[5]Tensorflow Lite- machine learning at the edge!! | by Maheshwar Ligade | techwasti | Medium</p>
  2158.  
  2159.  
  2160.  
  2161. <p>[6] Google Developers Blog: Announcing TensorFlow Lite | googleblog.com</p>
  2162. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4-%ec%a0%81%ec%9a%a9%ea%b8%b0-2%eb%b6%80-ml-model-converter%ec%99%80-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c/">AI 명함촬영인식 &#8216;리오(RIO)&#8217; 적용기 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  2163. ]]></content:encoded>
  2164. <wfw:commentRss>https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4-%ec%a0%81%ec%9a%a9%ea%b8%b0-2%eb%b6%80-ml-model-converter%ec%99%80-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c/feed/</wfw:commentRss>
  2165. <slash:comments>1</slash:comments>
  2166. <post-id xmlns="com-wordpress:feed-additions:1">3447</post-id> </item>
  2167. <item>
  2168. <title>리멤버 유저에게 보다 깨끗한 명함 이미지 제공을 위한 이미지 복원 방법</title>
  2169. <link>https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/</link>
  2170. <comments>https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/#respond</comments>
  2171. <dc:creator><![CDATA[호림 박]]></dc:creator>
  2172. <pubDate>Fri, 18 Nov 2022 05:21:27 +0000</pubDate>
  2173. <category><![CDATA[AI Lab.]]></category>
  2174. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3398</guid>
  2175.  
  2176. <description><![CDATA[<p>안녕하세요. 드라마앤컴퍼니의 빅데이터센터 AILab 박호림입니다. 드라마앤컴퍼니 빅데이터 센터의 AI Lab은 Recommendation System, Ranking Model, Graph Neural Network, Natural Language Processing, Document Understanding, Computer Vision 등 연구 영역을 넓혀가고 있으며, 기반 연구를 통해 고객의 비즈니스에서 WOW 하는 경험을 제공하고자 노력하고 있습니다. 리멤버를 사용하는 많은 유저들은 본인의 명함 또는 주고받은 명함을 직접 촬영하여 등록하고 있습니다. 직접 촬영을 [&#8230;]</p>
  2177. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/">리멤버 유저에게 보다 깨끗한 명함 이미지 제공을 위한 이미지 복원 방법</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  2178. ]]></description>
  2179. <content:encoded><![CDATA[
  2180. <p>안녕하세요. 드라마앤컴퍼니의 빅데이터센터 AILab 박호림입니다.</p>
  2181.  
  2182.  
  2183.  
  2184. <p>드라마앤컴퍼니 빅데이터 센터의 AI Lab은 Recommendation System, Ranking Model, Graph Neural Network, Natural Language Processing, Document Understanding, Computer Vision 등 연구 영역을 넓혀가고 있으며, 기반 연구를 통해 고객의 비즈니스에서 WOW 하는 경험을 제공하고자 노력하고 있습니다.</p>
  2185.  
  2186.  
  2187.  
  2188. <p>리멤버를 사용하는 많은 유저들은 본인의 명함 또는 주고받은 명함을 직접 촬영하여 등록하고 있습니다. 직접 촬영을 하다 보면 밝거나 어두운 또는 명함을 책상에 두거나 손으로 들거나 등의 다양한 환경에서 촬영하다 보니 명함 이미지를 복원하거나 다양한 후처리가 필요합니다. 따라서 이번 포스팅에서는 유저가 촬영한 명함 이미지에 대한 복원 방법에 대해 알아보고자 합니다.</p>
  2189.  
  2190.  
  2191.  
  2192. <h1>1. 명함 이미지 복원의 필요성과 이미지 복원 Task</h1>
  2193.  
  2194.  
  2195.  
  2196. <h2>명함 이미지 복원의 필요성</h2>
  2197.  
  2198.  
  2199.  
  2200. <ol><li>명함을 촬영하면 명함 외  배경 부분을 잘라내고 명함만 확대하여 사용자에게 보이도록 합니다. 여기서 원본이미지에서 명함 부분만 잘라내어 확대하기 때문에 저해상도(낮은 품질)로 유저에게 보이는 문제가 있어 고해상도로 복원을 필요로 합니다.</li><li>리멤버 앱을 통한 명함 촬영은 자연히 다양한 환경에서 촬영된 명함 이미지들이 포함되어 있습니다. 하지만 촬영 시 주변 환경에 따라, 카메라의 성능에 따라 명함을 촬영한 이미지에 노이즈가 내포되곤 합니다. 촬영한 이미지에서 명함을 잘라내는 데 큰 문제는 없지만, 사용자에게 깨끗한 명함 이미지를 제공하기 위해서는 노이즈를 제거하는 명함 이미지 복원 작업이 필요합니다.</li><li>실제 명함을 촬영하여 명함 이미지를 저장하기 때문에 명함 자체가 오염되거나 명함을 잡고 찍은 명함 이미지라면 해당 부분이 반영되어 저장됩니다. 많은 유저들은 리멤버 상에서 명함을 통한 다양한 교류와 활동을 하기에 오염된 명함을 깨끗한 명함으로 복원할 필요가 있습니다.</li></ol>
  2201.  
  2202.  
  2203.  
  2204. <p><img data-attachment-id="3401" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-17-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-2-06-48-1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?fit=2492%2C652&amp;ssl=1" data-orig-size="2492,652" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷-2022-11-17-오후-2.06.48-1" data-image-description="" data-image-caption="&lt;p&gt;응ㅇ&lt;/p&gt;
  2205. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?fit=300%2C78&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?fit=1024%2C268&amp;ssl=1" loading="lazy" width="2492" height="652" class="wp-image-3401" style="width: 3000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=2492%2C652&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?w=2492&amp;ssl=1 2492w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=300%2C78&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=1024%2C268&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=768%2C201&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=1536%2C402&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=2048%2C536&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=750%2C196&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.06.48-1.png?resize=1140%2C298&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2206.  
  2207.  
  2208.  
  2209. <p class="has-text-align-center has-small-font-size">그림 1. 저해상도 명함 이미지(좌), 흐릿한 명함 이미지(중), 명함 정보 일부가 가려진 명함 이미지(우)</p>
  2210.  
  2211.  
  2212.  
  2213. <h2>이미지 복원 Task</h2>
  2214.  
  2215.  
  2216.  
  2217. <p>리멤버에서 명함 이미지를 촬영하고 난 후 이미지 복원에 대한 문제에 대해 3가지 정도 Task로 정의할 수 있습니다.</p>
  2218.  
  2219.  
  2220.  
  2221. <h3>Super-Resolution</h3>
  2222.  
  2223.  
  2224.  
  2225. <p>Super-Resolution(SR)은 저해상도 이미지를 고해상도 이미지로 변환하는 Task를 의미합니다.</p>
  2226.  
  2227.  
  2228.  
  2229. <p class="has-text-align-center"><img data-attachment-id="3404" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b72-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림2.png?fit=680%2C447&amp;ssl=1" data-orig-size="680,447" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림2.png?fit=300%2C197&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림2.png?fit=680%2C447&amp;ssl=1" loading="lazy" width="680" height="447" class="wp-image-3404" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림2.png?resize=680%2C447&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림2.png?w=680&amp;ssl=1 680w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림2.png?resize=300%2C197&amp;ssl=1 300w" sizes="(max-width: 680px) 100vw, 680px" data-recalc-dims="1" /></p>
  2230.  
  2231.  
  2232.  
  2233. <p class="has-text-align-center has-small-font-size">그림 2. Super-Resolution 예시 이미지</p>
  2234.  
  2235.  
  2236.  
  2237. <h3>Denoising, Deblurring</h3>
  2238.  
  2239.  
  2240.  
  2241. <p>Denoising 이란 입력 이미지로부터 이미지에 존재하는 노이즈를 제거하는 Task를 의미합니다.</p>
  2242.  
  2243.  
  2244.  
  2245. <p>Deblurring 이란 흐릿한 이미지에서 Blur를 제거하여 깔끔한 이미지로 만드는 Task 입니다.</p>
  2246.  
  2247.  
  2248.  
  2249. <p class="has-text-align-center"><img data-attachment-id="3406" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-17-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-2-20-08/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?fit=1984%2C650&amp;ssl=1" data-orig-size="1984,650" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷-2022-11-17-오후-2.20.08" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?fit=300%2C98&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?fit=1024%2C335&amp;ssl=1" loading="lazy" width="1984" height="650" class="wp-image-3406" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=1984%2C650&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?w=1984&amp;ssl=1 1984w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=300%2C98&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=1024%2C335&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=768%2C252&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=1536%2C503&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=750%2C246&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-2.20.08.png?resize=1140%2C373&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2250.  
  2251.  
  2252.  
  2253. <p class="has-text-align-center has-small-font-size">그림 3. Denoising, Deblurring 예시 이미지</p>
  2254.  
  2255.  
  2256.  
  2257. <h3>Inpainting</h3>
  2258.  
  2259.  
  2260.  
  2261. <p>Inpainting 이란 오래된 사진 또는 화질이 번진 이미지에서 손실된 영역을 복구하는 Task입니다.</p>
  2262.  
  2263.  
  2264.  
  2265. <p class="has-text-align-center"><img data-attachment-id="3407" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b74-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?fit=720%2C358&amp;ssl=1" data-orig-size="720,358" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림4" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?fit=300%2C149&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?fit=720%2C358&amp;ssl=1" loading="lazy" width="720" height="358" class="wp-image-3407" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?resize=720%2C358&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?w=720&amp;ssl=1 720w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?resize=300%2C149&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림4.png?resize=360%2C180&amp;ssl=1 360w" sizes="(max-width: 720px) 100vw, 720px" data-recalc-dims="1" /></p>
  2266.  
  2267.  
  2268.  
  2269. <p class="has-text-align-center has-small-font-size">그림 4. Inpainting 예시 이미지</p>
  2270.  
  2271.  
  2272.  
  2273. <h1>2. 전통적 이미지 복원 방법</h1>
  2274.  
  2275.  
  2276.  
  2277. <h3>Super-Resolution</h3>
  2278.  
  2279.  
  2280.  
  2281. <p class="has-text-align-center"><img data-attachment-id="3408" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b75-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?fit=1746%2C1690&amp;ssl=1" data-orig-size="1746,1690" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림5" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?fit=300%2C290&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?fit=1024%2C991&amp;ssl=1" loading="lazy" width="1746" height="1690" class="wp-image-3408" style="width: 600px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=1746%2C1690&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?w=1746&amp;ssl=1 1746w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=300%2C290&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=1024%2C991&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=768%2C743&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=1536%2C1487&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=750%2C726&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림5.png?resize=1140%2C1103&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2282.  
  2283.  
  2284.  
  2285. <p class="has-text-align-center has-small-font-size">그림 5. Interpolation 종류</p>
  2286.  
  2287.  
  2288.  
  2289. <p>Super-Resolution Task를 해결하기 위해 전통적으로 많이 쓰는 방법의 하나는 Interpolation입니다. Interpolation이란 알고 있는 값을 가지는 두 점 사이의 어떠한 지점의 값을 추정하는 방법을 의미합니다.</p>
  2290.  
  2291.  
  2292.  
  2293. <p>Super-Resolution을 해결하기 위한 Interpolation으로는 Bilinear interpolation, Bicubic interpolation 등이 있습니다. linear interpolation이란 두 점 사이의 직선을 그리는 방법, 즉 1차 함수에 해당하며 Cubic interpolation은 3차 함수 그래프 기준으로 값을 추정하는 방법입니다. 이 방법들을 2차원으로 확장해 Super-Resolution으로 적용하여 저해상도 이미지를 고해상도 이미지로 변환시켜줍니다. 이러한 방법 외에도 Nearest, Area, Lanczos 등의 Interpolation이 존재합니다.</p>
  2294.  
  2295.  
  2296.  
  2297. <p class="has-text-align-center"><img data-attachment-id="3409" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b77-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?fit=2238%2C1440&amp;ssl=1" data-orig-size="2238,1440" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림7" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?fit=300%2C193&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?fit=1024%2C659&amp;ssl=1" loading="lazy" width="2238" height="1440" class="wp-image-3409" style="width: 700px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=2238%2C1440&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?w=2238&amp;ssl=1 2238w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=300%2C193&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=1024%2C659&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=768%2C494&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=1536%2C988&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=2048%2C1318&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=750%2C483&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7.png?resize=1140%2C734&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2298.  
  2299.  
  2300.  
  2301. <p class="has-text-align-center has-small-font-size">그림 6. Bilinear, Lanczos Interpolation 테스트 이미지</p>
  2302.  
  2303.  
  2304.  
  2305. <p>그림 6은 360&#215;270 사이즈의 명함 이미지를 두 가지 interpolation으로 변환한 결과 이미지입니다. Bilinear, Lanczos interpolation을 거친 두 결과 이미지를 보면 Lanczos interpolation 결과가 조금 더 선명하게 나타납니다. 하지만 두 결과 모두 좋지 않은 해상도를 보여주고 있습니다.</p>
  2306.  
  2307.  
  2308.  
  2309. <p>사실 Interpolation은 Opencv에서 이미지 사이즈를 축소, 확대 시킬때 사용하는 방법으로 Super Resolution으로 부르기 애매한 부분이 있으며 Interpolation을 통한 Resize는 좋은 결과를 얻기 어려운 부분이 있습니다. 또 다른 Super-Resolution solution으로는 저해상도 이미지를 만드는 Image degradation model을 정의하고 Inverse problem으로 접근하는 방법이 존재합니다.</p>
  2310.  
  2311.  
  2312.  
  2313. <h3>Denoising</h3>
  2314.  
  2315.  
  2316.  
  2317. <p>De-noising Task를 해결하는 전통적 방법 중 필터링을 이용해 노이즈를 제거하는 방법이 존재합니다. 대중적인 방법으로는 Gaussian, Bilateral, Median filtering, Non-Local means filtering 등이 존재합니다.</p>
  2318.  
  2319.  
  2320.  
  2321. <ol><li>Gaussian filtering : Gaussian filtering은 현 픽셀값과 이웃 픽셀 값들의 가중 평균을 이용해 현재 픽셀 값을 교체하는 방법입니다. Gaussian filtering은 이미지가 공간적으로 천천히 변하기 때문에 가까이 있는 픽셀들은 비슷한 값을 갖는다는 가정하에 만들어진 방법으로, 현재 픽셀에 가까울 수록 더 큰 가중치 값을 갖고 멀수록 작은 가중치 값을 갖습니다. 하지만 이 방법은 Edge 같은 부분을 뭉그러트리기 때문에 노이즈 제거에는 단점으로 나타납니다.</li><li>Bilateral filtering : Gaussian filtering을 보완한 방법으로 Bilateral filtering이 등장했는데, Edge 정보를 보존하면서 노이즈를 제거하는 방법으로 현재 픽셀과 이웃 픽셀 사이의 거리와 픽셀 값의 차이를 동시에 가중치에 반영하여 픽셀간의 거리만 반영한 Gaussian filtering을 보완한 방법입니다.</li><li>Non-Local means filtering[1] : 2번의 Bilateral filtering 방법도 문제점이 있습니다. Bilateral filtering은 픽셀간 거리와 픽셀 값 차이를 사용하는데, 픽셀값만을 비교하게 되어 위치적 요소를 고려하지 못하기 때문에 너무 심한 노이즈를 갖는 이미지의 경우 픽셀의 평균을 구해 연산하는데 문제점이 존재합니다. 이런 Bilateral Filtering 을 보완한 방법으로 Non-Local means filtering이 등장합니다. Non-Local means filtering은 비교하고자 하는 지점의 픽셀만 보는 것이 아니라 해당 픽셀에 대한 주변을 patch로 잘라내어 patch 사이의 거리를 계산합니다. patch까지 비슷하다고 판단되면 두 픽셀 간의 평균을 구해 노이즈를 제거하는 방식으로 진행됩니다. 따라서 Bilateral filtering과 비슷하지만 보완되어 성능이 뛰어나며, 딥러닝이 등장하고 Restoration에 적용되기 전까지 대중적으로 사용되어 왔습니다. 그림 7은 노이즈가 있는 4032&#215;3024 명함 이미지에 대해 Non-Local means filtering을 적용한 결과에 대한 이미지입니다.</li></ol>
  2322.  
  2323.  
  2324.  
  2325. <p class="has-text-align-center"><img data-attachment-id="3410" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b77_1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?fit=2520%2C724&amp;ssl=1" data-orig-size="2520,724" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림7_1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?fit=300%2C86&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?fit=1024%2C294&amp;ssl=1" loading="lazy" width="2520" height="724" class="wp-image-3410" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=2520%2C724&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?w=2520&amp;ssl=1 2520w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=300%2C86&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=1024%2C294&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=768%2C221&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=1536%2C441&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=2048%2C588&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=750%2C215&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림7_1.png?resize=1140%2C328&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2326.  
  2327.  
  2328.  
  2329. <p class="has-text-align-center has-small-font-size">그림 7. 명함 이미지 Non Local Means Filtering 테스트 결과</p>
  2330.  
  2331.  
  2332.  
  2333. <h3>Inpainting</h3>
  2334.  
  2335.  
  2336.  
  2337. <p>Inpainting이란 이미지의 손상, 열화, 누락된, 가려진, 보이지 않는 부분을 채워 완전한 이미지를 복원, 생성하는 것을 의미합니다. 전통적 Inpainting 방법으로는 Patch 기반, Diffusion 기반 두 가지 방법으로 볼 수 있습니다.</p>
  2338.  
  2339.  
  2340.  
  2341. <p>Patch 기반의 방법은 이미지에서 손상되지 않는 부분에서 가장 일치하는 후보 패치를 찾아 손상된 위치에 복사하는 방법입니다. Diffusion 기반의 방법은 이미지 컨텐츠에서 누락된 영역의 경계로부터 시작하여 누락된 영역 내부로 점차 채워가는 방법을 의미합니다.</p>
  2342.  
  2343.  
  2344.  
  2345. <h1>3. 딥러닝 기반 이미지 복원 방법</h1>
  2346.  
  2347.  
  2348.  
  2349. <p>딥러닝이 등장하고 발전함에 따라 전통적인 복원 방법에서 딥러닝을 활용한 이미지 복원 방법이 등장하기 시작했습니다.</p>
  2350.  
  2351.  
  2352.  
  2353. <h3>SRCNN[2]</h3>
  2354.  
  2355.  
  2356.  
  2357. <p class="has-text-align-center"><img data-attachment-id="3411" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b78-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?fit=1154%2C450&amp;ssl=1" data-orig-size="1154,450" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림8" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?fit=300%2C117&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?fit=1024%2C399&amp;ssl=1" loading="lazy" width="1154" height="450" class="wp-image-3411" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?resize=1154%2C450&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?w=1154&amp;ssl=1 1154w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?resize=300%2C117&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?resize=1024%2C399&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?resize=768%2C299&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?resize=750%2C292&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림8.png?resize=1140%2C445&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2358.  
  2359.  
  2360.  
  2361. <p class="has-text-align-center has-small-font-size">그림 8. SRCNN의 전체 구조</p>
  2362.  
  2363.  
  2364.  
  2365. <p>본 모델은 지도학습 모델이며, 저해상도 이미지와 고해상도 정답 이미지를 제공한 후 모델이 변환한 고해상도 이미지와 정답 이미지 간의 차이를 좁히도록 학습하는, 정답에 가까워지도록 하는 맵핑 함수를 찾는 모델입니다. 그림 8은 SRCNN의 전체 구조입니다. Bicubic interpolation으로 고해상도 이미지 사이즈와 동일하게 만든 후 임의의 Patch size 기준으로 분할하여 각 Patch의 High resolution에서의 Convolution 연산을 통해 추정합니다. 이후 Convolution 연산을 통해 고해상도 이미지로 Reconstruction 하는 구조로 설계된 모델입니다.</p>
  2366.  
  2367.  
  2368.  
  2369. <h3>DnCNN[3]</h3>
  2370.  
  2371.  
  2372.  
  2373. <p class="has-text-align-center"><img data-attachment-id="3412" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b79/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?fit=1826%2C404&amp;ssl=1" data-orig-size="1826,404" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림9" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?fit=300%2C66&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?fit=1024%2C227&amp;ssl=1" loading="lazy" width="1826" height="404" class="wp-image-3412" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=1826%2C404&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?w=1826&amp;ssl=1 1826w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=300%2C66&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=1024%2C227&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=768%2C170&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=1536%2C340&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=750%2C166&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림9.png?resize=1140%2C252&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2374.  
  2375.  
  2376.  
  2377. <p class="has-text-align-center has-small-font-size">그림 9. DnCNN의 전체 구조</p>
  2378.  
  2379.  
  2380.  
  2381. <p>위 SRCNN은 Super-Resolution task에 대한 모델이며 DnCNN은 Denoising task에 대한 모델입니다. 그림 9는 DnCNN의 전체 구조입니다. 정답 이미지에 Noise를 입혀 Noisy image를 생성하고 CNN 네트워크를 통해 Residual Image를 생성한 다음 정답 이미지와 평균제곱오차(MSE) 계산을 통해 차이를 학습하는 모델입니다.</p>
  2382.  
  2383.  
  2384.  
  2385. <h3>SRGAN[4]</h3>
  2386.  
  2387.  
  2388.  
  2389. <p class="has-text-align-center"><img data-attachment-id="3415" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b710/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?fit=1320%2C652&amp;ssl=1" data-orig-size="1320,652" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림10" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?fit=300%2C148&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?fit=1024%2C506&amp;ssl=1" loading="lazy" width="1320" height="652" class="wp-image-3415" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?resize=1320%2C652&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?w=1320&amp;ssl=1 1320w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?resize=300%2C148&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?resize=1024%2C506&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?resize=768%2C379&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?resize=750%2C370&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림10.png?resize=1140%2C563&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2390.  
  2391.  
  2392.  
  2393. <p class="has-text-align-center has-small-font-size">그림 10. SRGAN의 전체 구조</p>
  2394.  
  2395.  
  2396.  
  2397. <p>본 모델은 처음으로 GAN을 이용하여 Super-Resolution task에 적용한 논문입니다. Generator는 저해상도 이미지를 고해상도 이미지로 만들고, Discriminator가 생성된 고해상도 이미지와 정답 고해상도 이미지를 판별하며, 진짜를 가려내는 학습을 진행하는 구조의 모델입니다.</p>
  2398.  
  2399.  
  2400.  
  2401. <h3>SwinIR[5]</h3>
  2402.  
  2403.  
  2404.  
  2405. <p class="has-text-align-center"><img data-attachment-id="3414" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b711-1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?fit=2064%2C828&amp;ssl=1" data-orig-size="2064,828" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림11-1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?fit=300%2C120&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?fit=1024%2C411&amp;ssl=1" loading="lazy" width="2064" height="828" class="wp-image-3414" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=2064%2C828&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?w=2064&amp;ssl=1 2064w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=300%2C120&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=1024%2C411&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=768%2C308&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=1536%2C616&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=2048%2C822&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=750%2C301&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림11-1.png?resize=1140%2C457&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2406.  
  2407.  
  2408.  
  2409. <p class="has-text-align-center has-small-font-size">그림 11. SwinIR의 전체 구조</p>
  2410.  
  2411.  
  2412.  
  2413. <p>본 논문은 21년도에 나온 논문에 해당 연도 기준으로 Super-Resolution, Denoising Task에 대해 SOTA를 달성한 논문입니다. Vision transformer를 이용한 Image Restoration 모델들은 보통 이미지를 Patch 단위로 나누어 각 Patch 독립적으로 보아서 패치 단위에서의 이웃 픽셀에 대한 정보를 이용하지 못한 문제점이 있습니다. 본 논문에서는 Patch 단위에서만 Attention이 이루어지는 것이 문제점으로 보고 Patch 간의 Attention이 가능하도록 하는 Swin transformer 구조의 Image reestoration 모델입니다. 하지만 Transformer 모델이기에 리소스나 추론 시간 등 상대적으로 더 많은 자원을 사용하기에 실 서비스에 사용되기 위해서는 고려되야 할 점이 많습니다.</p>
  2414.  
  2415.  
  2416.  
  2417. <p class="has-text-align-center"><img data-attachment-id="3423" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-17-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-39-53/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?fit=1950%2C682&amp;ssl=1" data-orig-size="1950,682" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷 2022-11-17 오후 5.39.53" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?fit=300%2C105&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?fit=1024%2C358&amp;ssl=1" loading="lazy" width="1950" height="682" class="wp-image-3423" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=1950%2C682&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?w=1950&amp;ssl=1 1950w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=300%2C105&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=1024%2C358&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=768%2C269&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=1536%2C537&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=750%2C262&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-17-오후-5.39.53.png?resize=1140%2C399&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2418.  
  2419.  
  2420.  
  2421. <p class="has-text-align-center has-small-font-size">그림 12. SwinIR 테스트 결과</p>
  2422.  
  2423.  
  2424.  
  2425. <p>그림 12는 저해상도의 테스트 이미지를 SwinIR 모델의 입력으로 하여 추론된 출력 간 비교 이미지입니다. 위에 Interpolation으로 얻은 결과와 눈으로도 확연히 보이는 좋은 결과를 보여줍니다.</p>
  2426.  
  2427.  
  2428.  
  2429. <h3>NAFNet[6]</h3>
  2430.  
  2431.  
  2432.  
  2433. <p class="has-text-align-center"><img data-attachment-id="3425" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-18-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-1-45-43/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?fit=1232%2C382&amp;ssl=1" data-orig-size="1232,382" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷 2022-11-18 오후 1.45.43" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?fit=300%2C93&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?fit=1024%2C318&amp;ssl=1" loading="lazy" width="1232" height="382" class="wp-image-3425" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?resize=1232%2C382&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?w=1232&amp;ssl=1 1232w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?resize=300%2C93&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?resize=1024%2C318&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?resize=768%2C238&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?resize=750%2C233&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-18-오후-1.45.43.png?resize=1140%2C353&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2434.  
  2435.  
  2436.  
  2437. <p class="has-text-align-center has-small-font-size">그림 13. NAFNet baseline Architecture(좌), GLU 기반의 NAFNet Activation Fuction(우)</p>
  2438.  
  2439.  
  2440.  
  2441. <p class="has-text-align-left">22년도 ECCV에 발표된 논문으로 Denoising, Deblurring Task에 대한 이미지 복원 논문입니다. 새로운 모델 디자인을 제안하는 논문이 아닌, UNet[7] 모델 구조를 채택하여 Gated Linear Unit을 활용해 비선형 활성화 함수를 사용하지 않고 Denoising, Deblurring Task를 해결하는 논문입니다. 현재 Denoising, Deblurring Task에서 SOTA를 달성한 모델입니다.</p>
  2442.  
  2443.  
  2444.  
  2445. <p class="has-text-align-center"><br><img data-attachment-id="3433" data-permalink="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/kakaotalk_image_2022-11-18-15-07-38-1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?fit=2818%2C1850&amp;ssl=1" data-orig-size="2818,1850" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="KakaoTalk_Image_2022-11-18-15-07-38 (1)" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?fit=300%2C197&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?fit=1024%2C672&amp;ssl=1" loading="lazy" width="2818" height="1850" class="wp-image-3433" style="width: 1000px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=2818%2C1850&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?w=2818&amp;ssl=1 2818w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=300%2C197&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=1024%2C672&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=768%2C504&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=1536%2C1008&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=2048%2C1344&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=750%2C492&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/KakaoTalk_Image_2022-11-18-15-07-38-1.png?resize=1140%2C748&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2446.  
  2447.  
  2448.  
  2449. <p class="has-text-align-center has-small-font-size">그림 14. 노이즈 명함 이미지, 흐릿한 명함 이미지에 대한 NAFNet 모델 출력 결과</p>
  2450.  
  2451.  
  2452.  
  2453. <p>그림 14는 논문 저자가 학습한 NAFNet Pre-trained Model로 노이즈가 존재하는 명함 이미지와 흐릿한 명함 이미지를 각각 추론한 결과입니다. 아주 깨끗한 또는 글자가 선명하게 복원된 이미지는 아니지만 입력 이미지로부터 어느 정도 좋은 복원 결과를 보여주고 있습니다.</p>
  2454.  
  2455.  
  2456.  
  2457. <h1>4. 결론</h1>
  2458.  
  2459.  
  2460.  
  2461. <p>지금까지 전통적인 이미지 복원 방법부터 딥러닝 기반의 이미지 복원 방법을 간단하게 살펴보았습니다. 딥러닝 기반의 이미지 복원 방법들이 기존 전통적인 방법에 비해 월등한 성능을 보여주고 있지만, 다만 각각 해결해야 하는 문제에 대한 필요 정도의 성능, 리소스, 시간 등을 고려하여 가장 적절한 방법론을 선택하고 적용하는 것이 좋은 방향으로 판단됩니다.</p>
  2462.  
  2463.  
  2464.  
  2465. <p>리멤버 빅데이터 센터 AI Lab에서는 꾸준히 최신 연구를 활용하여 인재 추천 서비스, 광고 추천 서비스, 명함 인식 등 다양한 연구를 수행하고 계속해서 블로그에 글을 포스팅하려고 하고 있습니다. 지속적인 관심 부탁드립니다.</p>
  2466.  
  2467.  
  2468.  
  2469. <p>궁금하신 사항은 댓글을 통해 문의 부탁드리며 긴 글 읽어주셔서 감사합니다.<br></p>
  2470.  
  2471.  
  2472.  
  2473. <h3>Reference</h3>
  2474.  
  2475.  
  2476.  
  2477. <p>[1] Buades, Antoni, Bartomeu Coll, and J-M. Morel. &#8220;A non-local algorithm for image denoising.&#8221;&nbsp;<em>2005 IEEE computer society conference on computer vision and pattern recognition (CVPR&#8217;05)</em>. Vol. 2. Ieee, 2005.APA</p>
  2478.  
  2479.  
  2480.  
  2481. <p>[2] Dong, Chao, et al. &#8220;Image super-resolution using deep convolutional networks.&#8221;&nbsp;<em>IEEE transactions on pattern analysis and machine intelligence</em> &nbsp;38.2 (2015): 295-307.</p>
  2482.  
  2483.  
  2484.  
  2485. <p>[3] Zhang, Kai, et al. &#8220;Beyond a gaussian denoiser: Residual learning of deep cnn for image denoising.&#8221;&nbsp;<em>IEEE transactions on image processing</em> &nbsp;26.7 (2017): 3142-3155.</p>
  2486.  
  2487.  
  2488.  
  2489. <p>[4] Ledig, Christian, et al. &#8220;Photo-realistic single image super-resolution using a generative adversarial network.&#8221;&nbsp;<em>Proceedings of the IEEE conference on computer vision and pattern recognition</em> . 2017.</p>
  2490.  
  2491.  
  2492.  
  2493. <p>[5] Liang, Jingyun, et al. &#8220;Swinir: Image restoration using swin transformer.&#8221;&nbsp;<em>Proceedings of the IEEE/CVF International Conference on Computer Vision</em> . 2021.</p>
  2494.  
  2495.  
  2496.  
  2497. <p>[6] Chen, Liangyu, et al. &#8220;Simple baselines for image restoration.&#8221;&nbsp;<em>arXiv preprint arXiv:2204.04676</em>&nbsp;(2022).</p>
  2498.  
  2499.  
  2500.  
  2501. <p>[7] Ronneberger, Olaf, Philipp Fischer, and Thomas Brox. &#8220;U-net: Convolutional networks for biomedical image segmentation.&#8221;&nbsp;<em>International Conference on Medical image computing and computer-assisted intervention</em>. Springer, Cham, 2015.</p>
  2502. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/">리멤버 유저에게 보다 깨끗한 명함 이미지 제공을 위한 이미지 복원 방법</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  2503. ]]></content:encoded>
  2504. <wfw:commentRss>https://blog.dramancompany.com/2022/11/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%9c%a0%ec%a0%80%ec%97%90%ea%b2%8c-%eb%b3%b4%eb%8b%a4-%ea%b9%a8%eb%81%97%ed%95%9c-%eb%aa%85%ed%95%a8-%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%a0%9c%ea%b3%b5%ec%9d%84-%ec%9c%84/feed/</wfw:commentRss>
  2505. <slash:comments>0</slash:comments>
  2506. <post-id xmlns="com-wordpress:feed-additions:1">3398</post-id> </item>
  2507. <item>
  2508. <title>AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부 &#8211; 명함촬영인식 위한 Instance Segmentation &#038; Computer Vision</title>
  2509. <link>https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/</link>
  2510. <comments>https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/#comments</comments>
  2511. <dc:creator><![CDATA[민석 강]]></dc:creator>
  2512. <pubDate>Wed, 16 Nov 2022 02:47:19 +0000</pubDate>
  2513. <category><![CDATA[AI Lab.]]></category>
  2514. <category><![CDATA[AI 명함 촬영 인식]]></category>
  2515. <category><![CDATA[AI 적용기]]></category>
  2516. <category><![CDATA[Contour]]></category>
  2517. <category><![CDATA[findContours]]></category>
  2518. <category><![CDATA[getPerspectiveTransform]]></category>
  2519. <category><![CDATA[Instance Segmentation]]></category>
  2520. <category><![CDATA[Projection Transform]]></category>
  2521. <category><![CDATA[rio]]></category>
  2522. <category><![CDATA[RIO Detector]]></category>
  2523. <category><![CDATA[RIO Segmentor]]></category>
  2524. <category><![CDATA[Segmentation]]></category>
  2525. <category><![CDATA[warpPerspective]]></category>
  2526. <category><![CDATA[리오]]></category>
  2527. <category><![CDATA[명함촬영]]></category>
  2528. <category><![CDATA[명함촬영인식]]></category>
  2529. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3374</guid>
  2530.  
  2531. <description><![CDATA[<p>리멤버의 AI 명함촬영인식 ‘리오(RIO)’ 적용기 1부에서는 AI 명함촬영인식 ‘리오(RIO)’를 개발하게 된 이야기를 시작으로 명함촬영에서 해결하고자 하는 문제를 풀기 위한 다양한 방법들은 검토하고 리멤버 만의 명함촬영인식 방법으로 고안한 AI 명함촬영인식 ‘리오(RIO)’의 방법을 설명했습니다. </p>
  2532. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/">AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부 &#8211; 명함촬영인식 위한 Instance Segmentation &#038; Computer Vision</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  2533. ]]></description>
  2534. <content:encoded><![CDATA[
  2535. <div style="height:36px" aria-hidden="true" class="wp-block-spacer"></div>
  2536.  
  2537.  
  2538.  
  2539. <p class="has-medium-font-size">안녕하세요. 빅데이터센터 AI Lab 강민석입니다.</p>
  2540.  
  2541.  
  2542.  
  2543. <p class="has-medium-font-size">리멤버의 명함 촬영 인식은 유저가 명함을 등록하기 위한 촬영 순간에 명함을 인식하고 배경이 제거된 명함만을 사용자에게 보여주는 기술 입니다. 지금 이 시간에도 많은 사용자들이 명함을 촬영하고 있어 리멤버에서 더 정확하고 선명한 명함을 사용자에게 제공하고자 꾸준히 노력을 해왔습니다.</p>
  2544.  
  2545.  
  2546.  
  2547. <p class="has-medium-font-size">이번에 포스팅에서 소개할 <strong>명함 촬영 인식 AI 모델 ‘리오(RIO)’</strong>는 기존의 전통적인 컴퓨터 비전 기술인 Edge Detection, Hough Transform과 같은 기술에서 Deep Learning을 활용한 Instance Segmentation 기술로의 교체를 통해 사용자에게 더 다양한 환경에서 촬영할 수 있게 하고 선명하고 깨끗한 명함을 사용자에게 제공하고자 합니다.</p>
  2548.  
  2549.  
  2550.  
  2551. <p class="has-medium-font-size">이 AI 명함 촬영 인식 ‘리오’ 적용기 포스팅은 1부와 2부로 나누어 포스팅되어 있으며 이번 포스팅인 1부에서는 명함 촬영 인식 위한 Instance Segmentation &amp; Computer Vision 적용 방법을 다루고 2부에서는 ML Model Converter와 안드로이드 앱 적용기에 대해 포스팅 되어있습니다.</p>
  2552.  
  2553.  
  2554.  
  2555. <p class="has-medium-font-size"><strong>AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부 &#8211; 명함 촬영 인식 위한 Instance Segmentation &amp; Computer Vision</strong></p>
  2556.  
  2557.  
  2558.  
  2559. <p class="has-medium-font-size"><strong>AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기</strong></p>
  2560.  
  2561.  
  2562.  
  2563. <p class="has-medium-font-size">2부의 ML Model Converter와 안드로이드 앱 적용기 또한 많은 관심 부탁드립니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  2564.  
  2565.  
  2566.  
  2567. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2568.  
  2569.  
  2570.  
  2571. <h2><strong>명함 촬영의 다양한 환경 및 촬영 어려움</strong></h2>
  2572.  
  2573.  
  2574.  
  2575. <p class="has-medium-font-size">리멤버의 기존 명함 촬영 인식 방법에서 사용자들의 꾸준한 개선 요구가 있었습니다. 그 원인은 크게 3가지 정도라고 생각됩니다. 첫 번째로는 다양한 배경에서 명함 촬영, 두 번째로는 다양한 촬영 상황, 세 번째로는 촬영 시 제약 사항이 있습니다.</p>
  2576.  
  2577.  
  2578.  
  2579. <ol class="has-medium-font-size"><li><strong>다양한 배경에서의 명함 촬영 </strong>: 많은 리멤버 앱 사용자들이 명함을 촬영할 당시에 명함을 테이블 위에 놓고 찍는 환경 찍습니다. 하지만 생각보다 많은 사용자가 차량 안, 손에 들고, 키보드 위에 놓고 명함 사진을 찍는 경우도 많다 보니 촬영에 어려움이 있었습니다.</li><li><strong>다양한 촬영 상황</strong> : 너무 어둡거나 밝은 조명에서 촬영하거나 그림자가 짙은 곳에서의 촬영, 사용자가 걷거나 움직이는 촬영 환경에서도 촬영에 어려움을 겪고 있었습니다.</li><li><strong>촬영 시 제약사항</strong> : 환경적인 요소를 제한하기 위한 근접한 명함, 배경과 대조되는 환경에서의 제약이 실제 사용자들의 재촬영 또는 촬영시간의 증가로 이어졌었습니다.</li></ol>
  2580.  
  2581.  
  2582.  
  2583. <p class="has-medium-font-size">이러한 3가지 요소들을 해결하고자 AI 명함 촬영 인식 ‘리오(RIO)’는 리멤버의 명함촬영을 하는 사용자에게 더욱 더 쉽고 빠르게 깨끗한 명함 촬영을 제공하고자 개발되었습니다. 이후 아래의 글에서는 AI 명함 촬영 인식 모델을 설명하고자 합니다.</p>
  2584.  
  2585.  
  2586.  
  2587. <p class="has-text-align-center"><img data-attachment-id="3375" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-1-%e1%84%83%e1%85%a1%e1%84%8b%e1%85%a3%e1%86%bc%e1%84%92%e1%85%a1%e1%86%ab-%e1%84%92%e1%85%aa%e1%86%ab%e1%84%80%e1%85%a7%e1%86%bc-%e1%84%86%e1%85%b5/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?fit=2000%2C377&amp;ssl=1" data-orig-size="2000,377" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 1. 다양한 환경 및 촬영 상황" data-image-description="" data-image-caption="&lt;p&gt;그림 1. 다양한 환경 및 촬영 상황 (왼쪽-키보드 위 명함, 가운데-어두운 환경의 명함, 오른쪽-멀리서 찍은 명함)&lt;/p&gt;
  2588. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?fit=300%2C57&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?fit=1024%2C193&amp;ssl=1" loading="lazy" width="2000" height="377" class="wp-image-3375" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=2000%2C377&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=300%2C57&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=1024%2C193&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=768%2C145&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=1536%2C290&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=750%2C141&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-1.-다양한-환경-및-촬영-상황.png?resize=1140%2C215&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2589.  
  2590.  
  2591.  
  2592. <p class="has-text-align-center">그림 1. 다양한 환경 및 촬영 상황 (왼쪽-키보드 위 명함, 가운데-어두운 환경의 명함, 오른쪽-멀리서 찍은 명함)</p>
  2593.  
  2594.  
  2595.  
  2596. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2597.  
  2598.  
  2599.  
  2600. <h2><strong>AI 명함 촬영 인식의 Task</strong></h2>
  2601.  
  2602.  
  2603.  
  2604. <p class="has-medium-font-size">AI 명함 촬영 인식 리오(RIO)를 개발 하기에 앞서 다양한 문제 해결방법에 대해 리서치를 진행하게 되었습니다. 명함 촬영 인식이라는 문제를 해결하기 위한 Task들로 <strong>Rotated Object Detection, Keypoint Detection, Instance Segmentation</strong>으로 추려졌습니다. 따라서 각 Task는 서로 장단점들이 존재하고 저희 명함에 적합한 Task는 Instance Segmentation이라 판단했습니다.</p>
  2605.  
  2606.  
  2607.  
  2608. <p class="has-medium-font-size">우선적으로 <strong>Rotated Object Detection</strong>은 다른 Task에 비해 쉬운 테스크를 갖고 있어 학습에 유리하고 명함의 방향까지 찾아 줄 수 있다는 장점이 있습니다. 하지만 명함 촬영 시에 카메라 특성 때문에 실제 사물이 이미지에 투영되는 2차원 이미지로 표현되는데 이는 명함이 직사각형으로 표현되지 않는 한계를 갖는 것을 의미하며 저희가 해결하고자 하는 문제를 해결할 수 없었습니다.</p>
  2609.  
  2610.  
  2611.  
  2612. <p class="has-medium-font-size"><strong>Keypoint Detection</strong>은 명함의 4개의 점을 바로 찾아 사용자에게 제공되므로 모델 결과물에 대한 후처리가 따로 필요 없다는 장점을 갖고 있습니다. 하지만 Keypoint Detection으로 찾는 4개의 점의 정확도와 리멤버 촬영시 원하는 정확도보다는 못 미치는 결과를 얻었습니다. 또한, 동그라미 및 다각형등의 다양한 명함 Shape를 표현하지 못하는 문제가 존재 했습니다.</p>
  2613.  
  2614.  
  2615.  
  2616. <p class="has-medium-font-size"><strong>Instance Segmentation</strong>의 경우 실제 사물이 이미지에 투영되는 특성에 상관없이 다양한 모양의 명함의 Shape을 찾아주고 위에 설명한 다른 Task들보다 정확하게 명함을 찾아주는 결과를 보여줬습니다. 하지만 Segmentation 결과 자체를 사용하지 않고 추가적인 후처리를 통해 사용자에게 제공해주어야 했습니다.</p>
  2617.  
  2618.  
  2619.  
  2620. <p class="has-text-align-center"><img data-attachment-id="3376" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-2-task%e1%84%8b%e1%85%b4-%e1%84%80%e1%85%a7%e1%86%af%e1%84%80%e1%85%aa/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?fit=2000%2C487&amp;ssl=1" data-orig-size="2000,487" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 2. Task의 결과" data-image-description="" data-image-caption="&lt;p&gt;그림 2. Rotated Object Detection[1], Keypoint Detection[2], Instance Segmentation[3] 각 Task의 결과 &lt;/p&gt;
  2621. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?fit=300%2C73&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?fit=1024%2C249&amp;ssl=1" loading="lazy" width="2000" height="487" class="wp-image-3376" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=2000%2C487&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=300%2C73&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=1024%2C249&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=768%2C187&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=1536%2C374&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=750%2C183&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-2.-Task의-결과.png?resize=1140%2C278&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2622.  
  2623.  
  2624.  
  2625. <p class="has-text-align-center">그림 2. Rotated Object Detection[1], Keypoint Detection[2], Instance Segmentation[3] 각 Task의 결과</p>
  2626.  
  2627.  
  2628.  
  2629. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2630.  
  2631.  
  2632.  
  2633. <h2><strong>AI 명함 촬영 인식 모델의 파이프 라인</strong></h2>
  2634.  
  2635.  
  2636.  
  2637. <p class="has-medium-font-size">이번에 새롭게 배포되는 AI 명함 촬영 인식 모델 ‘리오(RIO)’는 아래의 흐름으로 입력된 이미지를 처리하게 됩니다. 사용자에게 실시간으로 명함을 찾아 사용자 화면에 표현해주기 위해 명함의 위치를 <strong>RIO Detector</strong>가 이미지 위에 동그라미로 표현해주게 됩니다. 사용자가 촬영 버튼을 클릭하게 되면 촬영된 명함 이미지를  <strong>RIO Segmentor</strong>를 통해 명함의 영역을 찾아내고 사용자에게 명함 이미지만으로 보이게끔 배경을 잘라내고 명함의 형태를 변형하여 명함의 이미지를 보여주게 됩니다. 아래의 내용에서 기능을 하나씩 설명하겠습니다.</p>
  2638.  
  2639.  
  2640.  
  2641. <p class="has-text-align-center"><img data-attachment-id="3377" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-3-ai-%e1%84%86%e1%85%a7%e1%86%bc%e1%84%92%e1%85%a1%e1%86%b7-%e1%84%8e%e1%85%aa%e1%86%af%e1%84%8b%e1%85%a7%e1%86%bc-%e1%84%8b%e1%85%b5%e1%86%ab%e1%84%89/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?fit=2000%2C914&amp;ssl=1" data-orig-size="2000,914" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 3 AI 명함 촬영 인식 모델의 파이프 라인" data-image-description="" data-image-caption="&lt;p&gt;그림 3 AI 명함 촬영 인식 모델의 파이프 라인&lt;/p&gt;
  2642. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?fit=300%2C137&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?fit=1024%2C468&amp;ssl=1" loading="lazy" width="2000" height="914" class="wp-image-3377" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=2000%2C914&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=300%2C137&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=1024%2C468&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=768%2C351&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=1536%2C702&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=750%2C343&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-3-AI-명함-촬영-인식-모델의-파이프-라인.png?resize=1140%2C521&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2643.  
  2644.  
  2645.  
  2646. <p class="has-text-align-center">그림 3 AI 명함 촬영 인식 모델의 파이프 라인</p>
  2647.  
  2648.  
  2649.  
  2650. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2651.  
  2652.  
  2653.  
  2654. <h2><strong>RIO Detector(Object Detection)</strong></h2>
  2655.  
  2656.  
  2657.  
  2658. <p class="has-text-align-center"><img data-attachment-id="3379" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-4-rio-detector-%e1%84%8c%e1%85%a5%e1%86%a8%e1%84%8b%e1%85%ad%e1%86%bc%e1%84%83%e1%85%ac%e1%86%ab-%e1%84%85%e1%85%b5%e1%84%86%e1%85%a6%e1%86%b7%e1%84%87/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-RIO-Detector-적용된-리멤버-앱-min.gif?fit=262%2C640&amp;ssl=1" data-orig-size="262,640" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 4. RIO Detector 적용된 리멤버 앱-min" data-image-description="" data-image-caption="&lt;p&gt;그림 4. RIO Detector 적용된 리멤버 앱&lt;/p&gt;
  2659. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-RIO-Detector-적용된-리멤버-앱-min.gif?fit=123%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-RIO-Detector-적용된-리멤버-앱-min.gif?fit=262%2C640&amp;ssl=1" loading="lazy" width="262" height="640" class="wp-image-3379" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-4.-RIO-Detector-적용된-리멤버-앱-min.gif?resize=262%2C640&#038;ssl=1" alt="" data-recalc-dims="1"></p>
  2660.  
  2661.  
  2662.  
  2663. <p class="has-text-align-center">그림 4. RIO Detector 적용된 리멤버 앱</p>
  2664.  
  2665.  
  2666.  
  2667. <p class="has-medium-font-size"><strong>RIO Detector</strong>는 사용자가 촬영한 이미지에서 명함의 위치 및 크기를 직사각형 형태로 찾는 작업입니다. 이는 사용자에게 명함의 위치를 인지하게 해주고 명함의 촬영이 준비 되었다는 의미를 갖습니다. 명함 촬영시에 가이드 역할을 합니다.</p>
  2668.  
  2669.  
  2670.  
  2671. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2672.  
  2673.  
  2674.  
  2675. <h2><strong>RIO Segmentor(Instance Segmentation)</strong></h2>
  2676.  
  2677.  
  2678.  
  2679. <p class="has-text-align-center"><img data-attachment-id="3380" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-5-%e1%84%8b%e1%85%b5%e1%84%8c%e1%85%b5%e1%86%ab%e1%84%92%e1%85%aa%e1%84%83%e1%85%ac%e1%86%ab-%e1%84%86%e1%85%a7%e1%86%bc%e1%84%92%e1%85%a1%e1%86%b7/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?fit=2000%2C1075&amp;ssl=1" data-orig-size="2000,1075" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 5. 이진화된 명함의 영역(세그멘테이션 결과)" data-image-description="" data-image-caption="&lt;p&gt;그림 5. 이진화된 명함의 영역(세그멘테이션 결과)&lt;/p&gt;
  2680. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?fit=300%2C161&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?fit=1024%2C550&amp;ssl=1" loading="lazy" width="2000" height="1075" class="wp-image-3380" style="width: 500px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=2000%2C1075&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=300%2C161&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=1024%2C550&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=768%2C413&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=1536%2C826&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=750%2C403&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-5.-이진화된-명함의-영역세그멘테이션-결과.png?resize=1140%2C613&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" />.     <img data-attachment-id="3381" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-6-%e1%84%8b%e1%85%af%e1%86%ab%e1%84%87%e1%85%a9%e1%86%ab-%e1%84%8b%e1%85%b5%e1%84%86%e1%85%b5%e1%84%8c%e1%85%b5%e1%84%8b%e1%85%aa-%e1%84%89%e1%85%a6/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?fit=1166%2C622&amp;ssl=1" data-orig-size="1166,622" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 6. 원본 이미지와 세그멘테이션 매핑(예상) 결과" data-image-description="" data-image-caption="&lt;p&gt;그림 6. 원본 이미지와 세그멘테이션 매핑(예상) 결과&lt;/p&gt;
  2681. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?fit=300%2C160&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?fit=1024%2C546&amp;ssl=1" loading="lazy" width="1166" height="622" class="wp-image-3381" style="width: 500px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?resize=1166%2C622&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?w=1166&amp;ssl=1 1166w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?resize=300%2C160&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?resize=1024%2C546&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?resize=768%2C410&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?resize=750%2C400&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-원본-이미지와-세그멘테이션-매핑예상-결과.png?resize=1140%2C608&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2682.  
  2683.  
  2684.  
  2685. <p class="has-text-align-left">                                              그림 5. 이진화된 명함의 영역(세그멘테이션 결과)                                                 그림 6. 원본 이미지와 세그멘테이션 매핑(예상) 결과</p>
  2686.  
  2687.  
  2688.  
  2689. <p class="has-text-align-left has-medium-font-size"><strong>RIO Segmentor</strong>는 사용자가 촬영 버튼 클릭 시 동작하게 됩니다. 사용자가 촬영한 이미지에서 입력 이미지의(640&#215;640) 모든 픽셀에 대해 명함 인지 아닌지를 판단하여 이진화된 명함의 영역을 찾게 됩니다. RIO Segmentor로 찾게 된 이진화된 명함의 영역(명함의 Segment)을 후처리를 통하여 정제된 명함 이미지로 변환하게 됩니다.</p>
  2690.  
  2691.  
  2692.  
  2693. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2694.  
  2695.  
  2696.  
  2697. <h2><strong>Post-Processing</strong></h2>
  2698.  
  2699.  
  2700.  
  2701. <p class="has-medium-font-size">RIO Segmentor로 찾아낸 이진화된 명함의 영역(명함의 Segment)을 통해 사용자에게 보여주는 명함 이미지로 변환하는 일련의 작업을 <strong>Post-Processing</strong>이라고 부르고, 내부적으로 외곽선 검출→최소 넓이 사각형 검출→최소 거리 꼭짓점 검출→투영 변환 순으로 진행하게 됩니다.</p>
  2702.  
  2703.  
  2704.  
  2705. <h3><strong>외곽선 검출 (Contour)</strong></h3>
  2706.  
  2707.  
  2708.  
  2709. <p class="has-text-align-center"><img data-attachment-id="3383" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-6-%e1%84%86%e1%85%a7%e1%86%bc%e1%84%92%e1%85%a1%e1%86%b7%e1%84%8b%e1%85%b5%e1%84%86%e1%85%b5%e1%84%8c%e1%85%b5%e1%84%8b%e1%85%b4-%e1%84%8b%e1%85%ac/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?fit=2000%2C709&amp;ssl=1" data-orig-size="2000,709" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 6. 명함이미지의 외각선 검출 예시" data-image-description="" data-image-caption="&lt;p&gt;그림 6. 명함이미지의 외곽선 검출 예시&lt;/p&gt;
  2710. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?fit=300%2C106&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?fit=1024%2C363&amp;ssl=1" loading="lazy" width="2000" height="709" class="wp-image-3383" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=2000%2C709&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=300%2C106&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=1024%2C363&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=768%2C272&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=1536%2C545&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=750%2C266&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-6.-명함이미지의-외각선-검출-예시.png?resize=1140%2C404&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2711.  
  2712.  
  2713.  
  2714. <p class="has-text-align-center">그림 6. 명함이미지의 외곽선 검출 예시</p>
  2715.  
  2716.  
  2717.  
  2718. <p class="has-medium-font-size">RIO Segmentor으로 찾게 된 이진화된 명함의 영역(Segment)의 가장 밖에 있는 외곽선을 찾는 작업입니다. OpenCV의 <code><strong>findContours()</strong></code>를 활용하여 외곽선을 찾습니다.</p>
  2719.  
  2720.  
  2721.  
  2722. <div style="height:33px" aria-hidden="true" class="wp-block-spacer"></div>
  2723.  
  2724.  
  2725.  
  2726. <h3><strong>최소 넓이 직사각형 검출 (Minimum Area Rectangle)</strong></h3>
  2727.  
  2728.  
  2729.  
  2730. <p class="has-text-align-center"><img data-attachment-id="3384" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-7-minarearect-%e1%84%80%e1%85%a7%e1%86%af%e1%84%80%e1%85%aa-%e1%84%8b%e1%85%b5%e1%84%86%e1%85%b5%e1%84%8c%e1%85%b5/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?fit=2000%2C700&amp;ssl=1" data-orig-size="2000,700" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 7. minAreaRect() 결과 이미지" data-image-description="" data-image-caption="&lt;p&gt;그림 7. minAreaRect() 결과 이미지 &#8211; 왼쪽 OpenCV Contour Feature 예시[4], 오른쪽 명함이미지 결과 예시&lt;/p&gt;
  2731. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?fit=300%2C105&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?fit=1024%2C358&amp;ssl=1" loading="lazy" width="2000" height="700" class="wp-image-3384" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=2000%2C700&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=300%2C105&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=1024%2C358&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=768%2C269&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=1536%2C538&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=750%2C263&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-7.-minAreaRect-결과-이미지.png?resize=1140%2C399&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2732.  
  2733.  
  2734.  
  2735. <p class="has-text-align-center">그림 7. minAreaRect() 결과 이미지 &#8211; 왼쪽 OpenCV Contour Feature 예시[4], 오른쪽 명함이미지 결과 예시</p>
  2736.  
  2737.  
  2738.  
  2739. <p class="has-medium-font-size">OpenCV 함수인 <strong>minAreaRect()</strong> 를 사용하여 명함의 영역(Segment)을 감싸는 <strong>Minimum Area Rectangle(최소 넓이 직사각형)</strong>을 찾습니다. 위 그림에서 빨간색의 사각형이 회전을 포함한 최소 넓이를 갖는 직사각형입니다. 연두색의 사각형이 일반적으로 사용되는 Bounding Box(Object Detection의 결과)를 나타내고 회전이 없는 최소 넓이를 갖는 직사각형입니다.</p>
  2740.  
  2741.  
  2742.  
  2743. <div style="height:33px" aria-hidden="true" class="wp-block-spacer"></div>
  2744.  
  2745.  
  2746.  
  2747. <h3><strong>최소 거리 꼭짓점 검출 (Minimum Distance Point)</strong></h3>
  2748.  
  2749.  
  2750.  
  2751. <p class="has-text-align-center"><img data-attachment-id="3385" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-8-%e1%84%8e%e1%85%ac%e1%84%89%e1%85%a9%e1%84%80%e1%85%a5%e1%84%85%e1%85%b5-%e1%84%91%e1%85%a9%e1%84%8b%e1%85%b5%e1%86%ab%e1%84%90%e1%85%b3-%e1%84%80/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?fit=2000%2C551&amp;ssl=1" data-orig-size="2000,551" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 8. 최소거리 포인트 검출 방법" data-image-description="" data-image-caption="&lt;p&gt;그림 8. 최소거리 포인트 검출 방법&lt;/p&gt;
  2752. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?fit=300%2C83&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?fit=1024%2C282&amp;ssl=1" loading="lazy" width="2000" height="551" class="wp-image-3385" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=2000%2C551&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=300%2C83&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=1024%2C282&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=768%2C212&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=1536%2C423&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=750%2C207&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-8.-최소거리-포인트-검출-방법.png?resize=1140%2C314&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2753.  
  2754.  
  2755.  
  2756. <p class="has-text-align-center">그림 8. 최소거리 포인트 검출 방법</p>
  2757.  
  2758.  
  2759.  
  2760. <p class="has-medium-font-size"><strong>최소거리 꼭짓점 검출</strong>은 외곽선과 최소 넓이 직사각형을 활용해 최종적인 명함의 4개의 꼭짓점을 찾는 작업입니다. 찾아낸 최소 넓이 직사각형의 4개의 꼭짓점(위 그림의 파란색 동그라미)과 외곽선을 이루는 점 간의 가장 가까운 4개의 꼭짓점(빨간색 동그라미)을 찾게 됩니다. 찾아낸 4개의 점(빨간색 동그라미)을 명함의 꼭짓점이라고 판단합니다.</p>
  2761.  
  2762.  
  2763.  
  2764. <div style="height:33px" aria-hidden="true" class="wp-block-spacer"></div>
  2765.  
  2766.  
  2767.  
  2768. <h3><strong>투영 변환 (Projection Transform)</strong></h3>
  2769.  
  2770.  
  2771.  
  2772. <p><img data-attachment-id="3386" data-permalink="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7-9-%e1%84%86%e1%85%a7%e1%86%bc%e1%84%92%e1%85%a1%e1%86%b7-%e1%84%8b%e1%85%b5%e1%84%86%e1%85%b5%e1%84%8c%e1%85%b5%e1%84%8b%e1%85%b4-%e1%84%90%e1%85%ae/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?fit=2000%2C613&amp;ssl=1" data-orig-size="2000,613" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림 9. 명함 이미지의 투영 변환 예시" data-image-description="" data-image-caption="&lt;p&gt;그림 9. 명함 이미지의 투영 변환 예시&lt;/p&gt;
  2773. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?fit=300%2C92&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?fit=1024%2C314&amp;ssl=1" loading="lazy" width="2000" height="613" class="wp-image-3386" style="width: 1300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=2000%2C613&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?w=2000&amp;ssl=1 2000w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=300%2C92&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=1024%2C314&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=768%2C235&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=1536%2C471&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=750%2C230&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림-9.-명함-이미지의-투영-변환-예시.png?resize=1140%2C349&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2774.  
  2775.  
  2776.  
  2777. <p class="has-text-align-center">그림 9. 명함 이미지의 투영 변환 예시</p>
  2778.  
  2779.  
  2780.  
  2781. <p class="has-medium-font-size"><strong>투영 변환</strong>은 사용자가 촬영한 사진 속 명함을 2차원 평면으로 펴주는 작업으로 OpenCV 함수인 <code><strong>getPerspectiveTransform()</strong></code> 를 활용해 투영 변환 행렬을 구하고 <code><strong>warpPerspective()</strong></code> 를 통해 촬영된 이미지를 명함을 명함 사이즈라고 판단되는 정방향으로 회전된 최소 넓이 직사각형의 형태로 변형하여 사용자에게 정제된 명함 이미지로 보이게 됩니다.</p>
  2782.  
  2783.  
  2784.  
  2785. <div style="height:59px" aria-hidden="true" class="wp-block-spacer"></div>
  2786.  
  2787.  
  2788.  
  2789. <h2><strong>AI 명함촬영인식 ‘리오(RIO)’ 적용기 1부를 맺으며</strong></h2>
  2790.  
  2791.  
  2792.  
  2793. <p class="has-medium-font-size"><strong>AI 명함촬영인식 ‘리오(RIO)’ 적용기 1부</strong>에서는 AI 명함촬영인식 ‘리오(RIO)’를 개발하게 된 이야기를 시작으로 명함촬영에서 해결하고자 하는 문제를 풀기 위한 다양한 방법들은 검토하고 리멤버 만의 명함촬영인식 방법으로 고안한 AI 명함촬영인식 ‘리오(RIO)’의 방법을 설명했습니다. <strong>AI 명함촬영인식 ‘리오(RIO)’ 적용기 2부 &#8211; ML Model Converter와 안드로이드 앱 적용기</strong>에서는 AI 명함촬영인식 ‘리오(RIO)’의 파이프 라인을 안드로이드에 적용하는 방법들과 다양한 시도들을 공유하고자 합니다.</p>
  2794.  
  2795.  
  2796.  
  2797. <p class="has-medium-font-size">리멤버 빅데이터 센터 AI Lab에서는 꾸준히 최신 연구를 활용하여 인재 추천 서비스, 광고 추천 서비스, 명함 인식 등 다양한 연구를 수행하고 계속해서 블로그에 글을 포스팅하려고 하고 있습니다. 지속적인 관심 부탁드립니다. 궁금하신 사항은 댓글을 통해 문의 부탁드리며 긴 글 읽어주셔서 감사합니다.</p>
  2798.  
  2799.  
  2800.  
  2801. <div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div>
  2802.  
  2803.  
  2804.  
  2805. <h1><strong>Reference</strong></h1>
  2806.  
  2807.  
  2808.  
  2809. <p>[1] Zhang, Luyang, et al. &#8220;Constraint Loss for Rotated Object Detection in Remote Sensing Images.&#8221;&nbsp;<em>Remote Sensing</em> 13.21 (2021): 4291.</p>
  2810.  
  2811.  
  2812.  
  2813. <p>[2] Xu, Yufei, et al. &#8220;ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation.&#8221;&nbsp;<em>arXiv preprint arXiv:2204.12484</em> (2022).</p>
  2814.  
  2815.  
  2816.  
  2817. <p>[3] Bolya, Daniel, et al. &#8220;Yolact: Real-time instance segmentation.&#8221;&nbsp;<em>Proceedings of the IEEE/CVF international conference on computer vision</em>. 2019.</p>
  2818.  
  2819.  
  2820.  
  2821. <p>[4] OpenCV: Contour Features Official Tutorials</p>
  2822. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/">AI 명함 촬영 인식 ‘리오(RIO)’ 적용기 1부 &#8211; 명함촬영인식 위한 Instance Segmentation &#038; Computer Vision</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  2823. ]]></content:encoded>
  2824. <wfw:commentRss>https://blog.dramancompany.com/2022/11/ai-%eb%aa%85%ed%95%a8-%ec%b4%ac%ec%98%81-%ec%9d%b8%ec%8b%9d-%eb%a6%ac%ec%98%a4rio-%ec%a0%81%ec%9a%a9%ea%b8%b0-1%eb%b6%80-%eb%aa%85%ed%95%a8%ec%b4%ac%ec%98%81%ec%9d%b8%ec%8b%9d-%ec%9c%84%ed%95%9c-ins/feed/</wfw:commentRss>
  2825. <slash:comments>1</slash:comments>
  2826. <post-id xmlns="com-wordpress:feed-additions:1">3374</post-id> </item>
  2827. <item>
  2828. <title>추천 시스템 서비스 적용을 위한 Elastic Search 도입기</title>
  2829. <link>https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/</link>
  2830. <comments>https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/#comments</comments>
  2831. <dc:creator><![CDATA[호현 황]]></dc:creator>
  2832. <pubDate>Tue, 08 Nov 2022 00:18:17 +0000</pubDate>
  2833. <category><![CDATA[AI Lab.]]></category>
  2834. <category><![CDATA[AWS OpenSearch]]></category>
  2835. <category><![CDATA[ElasticSearch]]></category>
  2836. <category><![CDATA[SimCSE]]></category>
  2837. <category><![CDATA[리멤버]]></category>
  2838. <category><![CDATA[리멤버 커뮤니티]]></category>
  2839. <category><![CDATA[추천시스템]]></category>
  2840. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3343</guid>
  2841.  
  2842. <description><![CDATA[<p>안녕하세요 빅데이터 센터 AI Lab 황호현 입니다. 저희 AI Lab에서는 리멤버 유저들에게 인공지능을 통해서 WoW한 경험을 주기 위해 Recommendation System, Ranking Model, Document Understanding, NLP등 다양한 연구를 진행하고 있습니다. 이번 포스트는 입사 후 맡은 첫 번째 프로젝트인 “리멤버 커뮤니티 새 글 피드 개인화 추천”를 진행하는 과정을 공유드리고자 합니다. 머신러닝 모델을 서비스에 활용하는데 모델 학습을 정확하게 [&#8230;]</p>
  2843. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/">추천 시스템 서비스 적용을 위한 Elastic Search 도입기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  2844. ]]></description>
  2845. <content:encoded><![CDATA[
  2846. <p>안녕하세요 빅데이터 센터 AI Lab 황호현 입니다.</p>
  2847.  
  2848.  
  2849.  
  2850. <p>저희 AI Lab에서는 리멤버 유저들에게 인공지능을 통해서 WoW한 경험을 주기 위해 Recommendation System, Ranking Model, Document Understanding, NLP등 다양한 연구를 진행하고 있습니다.</p>
  2851.  
  2852.  
  2853.  
  2854. <p>이번 포스트는 입사 후 맡은 첫 번째 프로젝트인 “리멤버 커뮤니티 새 글 피드 개인화 추천”를 진행하는 과정을 공유드리고자 합니다. 머신러닝 모델을 서비스에 활용하는데 모델 학습을 정확하게 하는 것도 중요하지만, 어떤 방법을 활용해서 서비스에 제공하도록 할 것인가도 굉장히 중요한 문제입니다.</p>
  2855.  
  2856.  
  2857.  
  2858. <p>추천 로직에 대한 서비스를 제공하는데 있어서 굉장히 많은 방법들이 존재합니다. 그 중에 저희는 Elastic Search를 기반으로 하여 추천 로직을 구축했고, 그 부분에 대해서 중점적으로 소개해 드리겠습니다.</p>
  2859.  
  2860.  
  2861.  
  2862. <hr class="wp-block-separator"/>
  2863.  
  2864.  
  2865.  
  2866. <h1>1. Introduction</h1>
  2867.  
  2868.  
  2869.  
  2870. <h3>1-1. 커뮤니티 피드 개인화 필요성</h3>
  2871.  
  2872.  
  2873.  
  2874. <p>리멤버에서는 직장인을 위한 커뮤니티를 운영하고 있습니다.</p>
  2875.  
  2876.  
  2877.  
  2878. <p>리멤버 커뮤니티는 크게 인사이트 / 직무 커뮤니티 / 관심사 커뮤니티 의 카테고리로 나뉩니다. 각 카테고리는 직장생활에서 얻을 수 있는 인사이트를 제공하고, 직무별로 정보를 공유할 수 있으며, 회사생활이나 기타 관심사에 대한 정보도 교류할 수 있는 공간입니다.</p>
  2879.  
  2880.  
  2881.  
  2882. <p class="has-text-align-center"><img data-attachment-id="3346" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_1_%e1%84%8f%e1%85%a5%e1%84%86%e1%85%b2%e1%84%82%e1%85%b5%e1%84%90%e1%85%b5%e1%84%86%e1%85%a6%e1%84%8b%e1%85%b5%e1%86%ab/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?fit=1524%2C3052&amp;ssl=1" data-orig-size="1524,3052" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_1_커뮤니티메인" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?fit=150%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?fit=511%2C1024&amp;ssl=1" loading="lazy" width="1524" height="3052" class="wp-image-3346" style="width: 300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=1524%2C3052&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?w=1524&amp;ssl=1 1524w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=150%2C300&amp;ssl=1 150w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=511%2C1024&amp;ssl=1 511w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=768%2C1538&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=767%2C1536&amp;ssl=1 767w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=1023%2C2048&amp;ssl=1 1023w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=750%2C1502&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_1_커뮤니티메인.png?resize=1140%2C2283&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2883.  
  2884.  
  2885.  
  2886. <p class="has-text-align-center has-small-font-size">리멤버 커뮤니티 메인화면 [1]</p>
  2887.  
  2888.  
  2889.  
  2890. <p>본 연구는 리멤버 커뮤니티에 존재하는 많은 정보 중 각 유저에게 가장 적합한 콘텐츠를 찾아 필요한 인사이트를 빠르게 얻도록 하는 것을 목적으로 했습니다. 그에 따라 유저가 가장 처음 접하는 새 글 피드의 개인화 추천 프로젝트를 진행했습니다.</p>
  2891.  
  2892.  
  2893.  
  2894. <h3>1-2. 새 글 피드에 업데이트 주기는 어떻게 되어야 하는가</h3>
  2895.  
  2896.  
  2897.  
  2898. <p>커뮤니티의 유형을 나눠보자면 카페 형 커뮤니티와, 플랫폼 형 커뮤니티로 나눌 수 있습니다.</p>
  2899.  
  2900.  
  2901.  
  2902. <p>카페 형 커뮤니티는 비교적 적은 수의 소속감이 강한 회원들 사이에 정보 교류를 목적으로 이루어진 곳이라고 볼 수 있습니다. 그 안에서 양질의 정보를 공유하면서 빠른 피드백을 주고 받을 수 있습니다. 그러나 새로운 회원의 유입이 적어 다양한 정보를 얻기는 힘듭니다.</p>
  2903.  
  2904.  
  2905.  
  2906. <p>플랫폼 형 커뮤니티는 카페 형 커뮤니티와 장점과 단점이 반대라고 할 수 있습니다. 한 가지 주제에 국한되지 않는 다양한 정보가 공유되고 있지만, 정보에 대한 휘발성이 있습니다.</p>
  2907.  
  2908.  
  2909.  
  2910. <p>리멤버는 계속해서 새로운 회원의 유입이 이루어지고 있으며, 리멤버 커뮤니티는 큰 주제 안에서 다양한 정보들이 공유되고 있기에 리멤버 커뮤니티는 플랫폼 형 커뮤니티가 가깝다고 판단했습니다.</p>
  2911.  
  2912.  
  2913.  
  2914. <p>따라서 유저들에게 양질의 콘텐츠를 맞춤형으로 제공해주는 것 뿐만 아니라, 실시간으로 콘텐츠를 제공해주는 것을 목표로 프로젝트를 진행 했습니다.</p>
  2915.  
  2916.  
  2917.  
  2918. <hr class="wp-block-separator"/>
  2919.  
  2920.  
  2921.  
  2922. <h1>2. Recommendation System</h1>
  2923.  
  2924.  
  2925.  
  2926. <h2>2-1. Contents-based Recommendation</h2>
  2927.  
  2928.  
  2929.  
  2930. <p>콘텐츠 기반 필터링 방식은 사용자가 특정 아이템을 선호하는 경우, 그 아이템과 비슷한 콘텐츠를 가진 다른 아이템을 추천해 주는 방식 입니다.</p>
  2931.  
  2932.  
  2933.  
  2934. <p class="has-text-align-center"><img data-attachment-id="3347" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_2_%e1%84%8f%e1%85%a9%e1%86%ab%e1%84%90%e1%85%a6%e1%86%ab%e1%84%8e%e1%85%b3%e1%84%80%e1%85%b5%e1%84%87%e1%85%a1%e1%86%ab%e1%84%8e%e1%85%ae%e1%84%8e/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?fit=1328%2C1018&amp;ssl=1" data-orig-size="1328,1018" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_2_콘텐츠기반추천예시" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?fit=300%2C230&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?fit=1024%2C785&amp;ssl=1" loading="lazy" width="1328" height="1018" class="wp-image-3347" style="width: 500px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?resize=1328%2C1018&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?w=1328&amp;ssl=1 1328w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?resize=300%2C230&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?resize=1024%2C785&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?resize=768%2C589&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?resize=750%2C575&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_2_콘텐츠기반추천예시.png?resize=1140%2C874&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2935.  
  2936.  
  2937.  
  2938. <p>유저가 관심분야의 글을 많이 읽을 것이라는 가정하에 콘텐츠 기반 필터링 방식을 선택했습니다. 커뮤니티에서 글을 추천해주는 방식으로는 유저가 커뮤니티에서 읽은 글과 유사한 글들을 추천해주는 방식을 적용하고자 했습니다.</p>
  2939.  
  2940.  
  2941.  
  2942. <h2>2-2. Unsupervised &#8211; SimCSE</h2>
  2943.  
  2944.  
  2945.  
  2946. <p>유사한 콘텐츠를 추천해주기 위해서는 추천이 필요한 각 게시물(콘텐츠)들을 잘 표현해주는 것이 중요합니다. 저희는 각 게시물을 잘 표현하기 위한 모델로 Sentence Representation 모델인 SimCSE(Simple Contrastive Learning of Sentence Embeddings)를 채택했습니다. Input Sentence에 대해서 dropout을 noise로 사용해 contrastive object에서 스스로를 예측하는 비지도학습이 가능한 모델 입니다. 아래 그림과 같이 한 mini-batch에 있는 문장들 안에서, dropout이 적용된 같은 문장을 postive pair로서 활용, 다른 문장들을 negative pair로써 활용하여 contrastive learning을 학습하는 Sentence Representation 모델 입니다.</p>
  2947.  
  2948.  
  2949.  
  2950. <p class="has-text-align-center"><img data-attachment-id="3348" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_3_simcse%e1%84%8b%e1%85%a8%e1%84%89%e1%85%b5/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?fit=1346%2C429&amp;ssl=1" data-orig-size="1346,429" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_3_SimCSE예시" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?fit=300%2C96&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?fit=1024%2C326&amp;ssl=1" loading="lazy" width="1346" height="429" class="wp-image-3348" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?resize=1346%2C429&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?w=1346&amp;ssl=1 1346w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?resize=300%2C96&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?resize=1024%2C326&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?resize=768%2C245&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?resize=750%2C239&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_3_SimCSE예시.png?resize=1140%2C363&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2951.  
  2952.  
  2953.  
  2954. <p class="has-text-align-center has-small-font-size">Unsupervised SimCSE 학습 과정 [6]</p>
  2955.  
  2956.  
  2957.  
  2958. <p>해당 모델의 loss function은 위 그림과 같습니다. 분자는 같은 문장을 다르게 표현한 것들의 유사도, 분모는 다른 문장을 다르게 표현한 것들의 유사도의 합입니다. 즉, 분자는 커지고, 분모는 작아질수록 같은 것들의 유사도는 높아지고, 다른 것들 사이의 유사도는 낮아질수록 loss가 작아지는 형태로 학습됩니다.</p>
  2959.  
  2960.  
  2961.  
  2962. <p>따라서 저희는 리멤버 커뮤니티의 글을 활용하여 Unsupervised learning(비지도학습) 방식으로 SimCSE를 fine-tuning했고 그를 통해서 리멤버 커뮤니티 도메인 최적화된 임베딩을 표현할 수 있도록 했습니다.</p>
  2963.  
  2964.  
  2965.  
  2966. <h1>3. Our Method</h1>
  2967.  
  2968.  
  2969.  
  2970. <h2>3-1. Contents Embedding</h2>
  2971.  
  2972.  
  2973.  
  2974. <p>콘텐츠를 구성하는 데이터들을 앞서 설명한 SimCSE 모델을 기반으로 임베딩 벡터를 추출합니다. 사용한 SimCSE 인코더는 transformer 기반의 모델인 BERT를 활용했습니다. 각 콘텐츠의 임베딩 벡터는 ”제목”, “본문”, “카테고리”, “좋아요 클릭 여부”, “댓글작성 여부”를 활용하여 생성했습니다. ”커뮤니티 유형”, “입력 시간” 역시 활용하려고 하였으나 추천 결과에 대한 정성 / 정량 평가를 기준으로 표현에서 제외 하게 되었습니다.</p>
  2975.  
  2976.  
  2977.  
  2978. <p class="has-text-align-center"><img data-attachment-id="3338" data-permalink="https://blog.dramancompany.com/image-2-4/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?fit=1608%2C2484&amp;ssl=1" data-orig-size="1608,2484" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?fit=194%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?fit=663%2C1024&amp;ssl=1" loading="lazy" width="1608" height="2484" class="wp-image-3338" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=1608%2C2484&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?w=1608&amp;ssl=1 1608w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=194%2C300&amp;ssl=1 194w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=663%2C1024&amp;ssl=1 663w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=768%2C1186&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=994%2C1536&amp;ssl=1 994w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=1326%2C2048&amp;ssl=1 1326w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=750%2C1159&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/image-2.png?resize=1140%2C1761&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  2979.  
  2980.  
  2981.  
  2982. <h2>3-2. 가중평균을 활용한 유저 임베딩 벡터 생성</h2>
  2983.  
  2984.  
  2985.  
  2986. <p>가중 평균은 데이터 세트에서 일부 요인의 상대적 중요도 또는 빈도를 고려합니다.</p>
  2987.  
  2988.  
  2989.  
  2990. <p>유저가 읽은 콘텐츠 임베딩의 가중 평균 값을 유저 임베딩으로써 활용했습니다. 유저 임베딩과 코사인 유사도가 높은 콘텐츠들을 추천해주는 방식으로 추천을 진행했습니다.</p>
  2991.  
  2992.  
  2993.  
  2994. <h5>변수를 가중치로써 활용</h5>
  2995.  
  2996.  
  2997.  
  2998. <p>여러 변수를 검증해봤을때 가장 성능이 좋았던 좋아요와 댓글 작성 여부를 활용해서 가중치를 적용하여 가중평균한 임배딩을 산출 했습니다.</p>
  2999.  
  3000.  
  3001.  
  3002. <p class="has-text-align-center"><img data-attachment-id="3350" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_5_%e1%84%8b%e1%85%b2%e1%84%8c%e1%85%a5%e1%84%8b%e1%85%b5%e1%86%b7%e1%84%87%e1%85%a2%e1%84%83%e1%85%b5%e1%86%bc%e1%84%89%e1%85%a2%e1%86%bc%e1%84%89/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?fit=3708%2C1328&amp;ssl=1" data-orig-size="3708,1328" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_5_유저임배딩생성" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?fit=300%2C107&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?fit=1024%2C367&amp;ssl=1" loading="lazy" width="3708" height="1328" class="wp-image-3350" style="width: 700px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=3708%2C1328&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?w=3708&amp;ssl=1 3708w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=300%2C107&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=1024%2C367&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=768%2C275&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=1536%2C550&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=2048%2C733&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=750%2C269&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?resize=1140%2C408&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_5_유저임배딩생성.png?w=3000&amp;ssl=1 3000w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  3003.  
  3004.  
  3005.  
  3006. <h2>3-3. 전체 추천 로직</h2>
  3007.  
  3008.  
  3009.  
  3010. <p>전체적인 추천 로직을 정리해보자면, 유저 임베딩과 유저가 참여중인 커뮤니티의 콘텐츠들과 유사도를 비교하여 가장 유사한 top K개를 추천해주는 로직 입니다.</p>
  3011.  
  3012.  
  3013.  
  3014. <p class="has-text-align-center"><img data-attachment-id="3351" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_6_%e1%84%8c%e1%85%a5%e1%86%ab%e1%84%8e%e1%85%a6%e1%84%8e%e1%85%ae%e1%84%8e%e1%85%a5%e1%86%ab%e1%84%85%e1%85%a9%e1%84%8c%e1%85%b5%e1%86%a8/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?fit=3352%2C1008&amp;ssl=1" data-orig-size="3352,1008" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_6_전체추천로직" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?fit=300%2C90&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?fit=1024%2C308&amp;ssl=1" loading="lazy" width="3352" height="1008" class="wp-image-3351" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=3352%2C1008&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?w=3352&amp;ssl=1 3352w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=300%2C90&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=1024%2C308&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=768%2C231&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=1536%2C462&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=2048%2C616&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=750%2C226&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?resize=1140%2C343&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_6_전체추천로직.png?w=3000&amp;ssl=1 3000w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  3015.  
  3016.  
  3017.  
  3018. <hr class="wp-block-separator"/>
  3019.  
  3020.  
  3021.  
  3022. <h1>4. 서비스 적용에 대한 문제</h1>
  3023.  
  3024.  
  3025.  
  3026. <h2>4-1. 속도 문제</h2>
  3027.  
  3028.  
  3029.  
  3030. <ul><li>유저가 접속할 때 마다 모델을 활용한 추론을 통해서 임베딩을 생성하면 시간이 오래 걸릴 것이라고 판단 했습니다.</li><li>기존에 고려한 방식<ul><li>MongoDB에 임베딩을 저장 후, 유저가 커뮤니티에 접속하면 임베딩을 추출하여 비교</li><li>MongoDB에서 추천 후보군에 대한 임베딩을 전부 추출하는데 걸리는 시간이 실시간 서비스로 적용하기에는 매우 어려운 수준</li><li>서비스를 제공할때 업데이트 주기를 길게 설정하여 서비스 적용</li></ul></li><li>변경된 방식<ul><li>ElasticSearch 도입으로 별도의 DB조회 없이 검색엔진 안에서 벡터 간 유사도 계산</li></ul></li></ul>
  3031.  
  3032.  
  3033.  
  3034. <h2>4-2. MongoDB</h2>
  3035.  
  3036.  
  3037.  
  3038. <ul><li>MongoDB 란?<ul><li>MongoDB는 기존의 테이블 기반 관계형 데이터베이스 구조가 아닌 문서 지향&nbsp;데이터 모델을 사용하는 교차 플랫폼 오픈 소스 데이터베이스입니다. 이러한 유형의 모델을 사용하면&nbsp;정형 및&nbsp;비정형 데이터를&nbsp;보다 쉽고 빠르게 통합할 수 있습니다.</li></ul></li><li>변경 전 방법<br><img data-attachment-id="3352" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_7_%e1%84%86%e1%85%a9%e1%86%bc%e1%84%80%e1%85%a9db%e1%84%92%e1%85%aa%e1%86%af%e1%84%8b%e1%85%ad%e1%86%bc/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?fit=3404%2C1208&amp;ssl=1" data-orig-size="3404,1208" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_7_몽고DB활용" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?fit=300%2C106&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?fit=1024%2C363&amp;ssl=1" loading="lazy" width="3404" height="1208" class="wp-image-3352" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=3404%2C1208&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?w=3404&amp;ssl=1 3404w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=300%2C106&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=1024%2C363&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=768%2C273&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=1536%2C545&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=2048%2C727&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=750%2C266&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?resize=1140%2C405&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_7_몽고DB활용.png?w=3000&amp;ssl=1 3000w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></li></ul>
  3039.  
  3040.  
  3041.  
  3042. <ul><li>처음 고려했던 서비스 제공 방식은 위와 같이 설명할 수 있습니다.<ol><li>유저가 리멤버 커뮤니티에 접속</li><li>MongoDB에서 유저의 임베딩 값을 추출</li><li>유저에게 추천될 수 있는 카테고리의 콘텐츠 임베딩 값들을 추출하여 유저 임베딩 값과</li><li>코사인 유사도를 비교</li><li>유저에게 추천되는 post id 들을 sorting하여 list 형태로 저장</li></ol></li></ul>
  3043.  
  3044.  
  3045.  
  3046. <p>MongoDB만을 활용해서 서비스에 적용했을때는 치명적인 문제가 있었습니다. 각 콘텐츠의 임베딩을 저장한 MongoDB collection에서 추천 후보군 몇 천 개의 임베딩을 추출하는 데 걸리는 시간이 오래걸리는 문제 입니다.</p>
  3047.  
  3048.  
  3049.  
  3050. <p><em><strong>총 소요시간 : 5 sec</strong></em></p>
  3051.  
  3052.  
  3053.  
  3054. <p>그래서 저희는 고민 끝에 빠른 속도로 코사인 유사도 기반 임베딩 벡터를 찾을 수 있는 검색엔진 ElasticSearch를 활용하기로 했습니다.</p>
  3055.  
  3056.  
  3057.  
  3058. <hr class="wp-block-separator"/>
  3059.  
  3060.  
  3061.  
  3062. <h1>5. ElasticSearch (OpenSearch) 도입</h1>
  3063.  
  3064.  
  3065.  
  3066. <h2>5-1. ElasticSearch란?</h2>
  3067.  
  3068.  
  3069.  
  3070. <p>Elasticsearch는 시간이 갈수록 증가하는 문제를 처리하는 분산형 RESTful 검색 및 분석 엔진입니다. Elastic Stack의 핵심 제품인 Elasticsearch는 데이터를 중앙에 저장하여 손쉽게 확장되는 광속에 가까운 빠른 검색, 정교하게 조정된 정확도, 강력한 분석을 제공합니다. 프로토타입에서 운영 배포까지 이어지는 모든 과정을 원활하게 처리할 수 있습니다. 단일 클러스터에서도 300개의 노드 클러스터에서와 동일한 방식으로 Elasticsearch를 실행합니다. 수평적 확장을 통해 매초당 수많은 양의 이벤트를 처리할 수 있으며, 클러스터에서 인덱스와 쿼리 배포를 자동화하여 보다 원활한 시스템 운영을 지원합니다.</p>
  3071.  
  3072.  
  3073.  
  3074. <h3>5-1-1. ElasticSearch 기능</h3>
  3075.  
  3076.  
  3077.  
  3078. <ul><li><strong>Elastic Enterprise Search</strong> : 데이터베이스 검색, 엔터프라이즈 시스템 오프로드, 전자 상거래, 고객 지원, 워크플레이스 콘텐츠, 웹사이트 또는 모든 애플리케이션에 Elastic을 사용하여 모든 사람이 필요한 것을 더 빨리 찾을 수 있습니다.</li><li><strong>Infrastructure Monitoring</strong> : AWS, Microsoft Azure 및 Google Cloud와 같은 클라우드 플랫폼을 포함하여 200개 이상의 통합을 지원하여 인프라를 원활하게 모니터링이 가능합니다.</li><li><strong>엔드포인트를 위한 Elastic Security</strong> : 엔드포인트를 위한 Elastic Security는 랜섬웨어 및 Malware를 방지하고, 지능적 위협을 탐지하며, 대응자에게 중요한 조사 컨텍스트를 제공합니다.</li></ul>
  3079.  
  3080.  
  3081.  
  3082. <ul><li>이 외에도 로그 모니터링, APM(Application Performance Monitoring), 위치탐색 등 모니터링 서비스와 검색 서비스를 제공하고 있습니다.</li></ul>
  3083.  
  3084.  
  3085.  
  3086. <p>ElasticSearch의 기능을 서비스에 적용하기 위하여 저희 팀에서는 Amazon OpenSearch Service를 활용했습니다.</p>
  3087.  
  3088.  
  3089.  
  3090. <h3>5-1-2. Amazon OpenSearch Service란?</h3>
  3091.  
  3092.  
  3093.  
  3094. <p>Amazon OpenSearch Service는 인프라 관리, 모니터링 및 유지 관리에 대한 걱정이나 OpenSearch 클러스터 운영에 대한 심층적인 전문성을 쌓을 필요 없이 OpenSearch 클러스터를 실행하고 확장할 수 있는 AWS 관리형 서비스입니다. OpenSearch는 Apache Lucene 검색 라이브러리로 구동되며 k-nearest neighbors(KNN) 검색, SQL, Anomaly Detection, Machine Learning Commons, Trace Analytics, 전체 텍스트 검색 등 다수의 검색 및 분석 기능을 지원합니다. OpenSearch는 ALv2 버전의 Elasticsearch 및 Kibana에서 포크를 만들어 유지하고 있습니다. Elasticsearch에서 제공되는 새로운 기능과 유사한 기능이 OpenSearch에 포함될 수 있지만(그 반대의 경우도 마찬가지) 모든 기능의 구현은 두 프로젝트 간에 고유합니다.</p>
  3095.  
  3096.  
  3097.  
  3098. <h4>k-NN(<em>k-nearest neighbors)</em></h4>
  3099.  
  3100.  
  3101.  
  3102. <p>k-NN을 사용하면 벡터 공간에서 포인트를 검색하고 해당 포인트에 대한 “가장 가까운 이웃”을 Euclidean 거리 또는 코사인 유사도로 찾을 수 있습니다.</p>
  3103.  
  3104.  
  3105.  
  3106. <p class="has-text-align-center"><img data-attachment-id="3353" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_8_knn%e1%84%8b%e1%85%a8%e1%84%89%e1%85%b5/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_8_knn예시.png?fit=489%2C361&amp;ssl=1" data-orig-size="489,361" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_8_knn예시" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_8_knn예시.png?fit=300%2C221&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_8_knn예시.png?fit=489%2C361&amp;ssl=1" loading="lazy" width="489" height="361" class="wp-image-3353" style="width: 300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_8_knn예시.png?resize=489%2C361&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_8_knn예시.png?w=489&amp;ssl=1 489w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_8_knn예시.png?resize=300%2C221&amp;ssl=1 300w" sizes="(max-width: 489px) 100vw, 489px" data-recalc-dims="1" /></p>
  3107.  
  3108.  
  3109.  
  3110. <h5>HNSW (Hierarchical Navigable Small World Algorithm)</h5>
  3111.  
  3112.  
  3113.  
  3114. <p class="has-text-align-center"><img data-attachment-id="3354" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_9_hswm/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?fit=400%2C291&amp;ssl=1" data-orig-size="400,291" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_9_HSWM" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?fit=300%2C218&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?fit=400%2C291&amp;ssl=1" loading="lazy" width="400" height="291" class="wp-image-3354" style="width: 300px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?resize=400%2C291&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?w=400&amp;ssl=1 400w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?resize=300%2C218&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_9_HSWM.png?resize=120%2C86&amp;ssl=1 120w" sizes="(max-width: 400px) 100vw, 400px" data-recalc-dims="1" /></p>
  3115.  
  3116.  
  3117.  
  3118. <p>OpenSearch에서 k-NN 검색문제에 대해서 빠르고 정확한 솔루션을 제공하기위해서 HNSW 알고리즘을 기반으로 하여 검색엔진이 동작합니다. 이 알고리즘은 적은 거리를 계산하고, 거리 계산 비용을 더 저렴하게 하도록 하는 것을 중점적으로 두고 있습니다.  입력 쿼리에 대한 가장 가까운 이웃을 찾기 위해 검색 프로세스는 최상위 계층의 그래프에서 가장 가까운 이웃을 찾고 이 점을 후속 계층에 대한 진입점으로 사용합니다.</p>
  3119.  
  3120.  
  3121.  
  3122. <h5>OpenSearch k-NN 데이터 입력 예시</h5>
  3123.  
  3124.  
  3125.  
  3126. <p>인덱스 생성 : k-NN 관련 index는 다음과 같이 설정할 수 있는데, “dimension”을 통해서 계산하는 임베딩 벡터의 차원을 사전에 정의합니다. </p>
  3127.  
  3128.  
  3129.  
  3130. <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">PUT /myindex
  3131. {
  3132. "settings": {
  3133.      "index.knn": true
  3134.      },
  3135. "mappings": {
  3136.     "properties": {
  3137.          "my_vector": {
  3138.                "type": "knn_vector",
  3139.                "dimension": 2
  3140.              }
  3141.         }
  3142.    }
  3143. }</pre>
  3144.  
  3145.  
  3146.  
  3147. <p>데이터 입력 : 콘텐츠에 대해서 생성된 임베딩 벡터 및 데이터 입력합니다. </p>
  3148.  
  3149.  
  3150.  
  3151. <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">PUT /myindex/_doc/1
  3152. {
  3153.  "my_vector": [1.5, 2.5]
  3154. }
  3155.  
  3156. PUT/myindex/_doc/2
  3157. {
  3158.  "my_vector": [2.5, 3.5]
  3159. }</pre>
  3160.  
  3161.  
  3162.  
  3163. <p>저희가 개발한 추천로직에서 Sentence Representation에 활용한 SimCSE 모델로 생성한 최종 임베딩 벡터는 1,638차원 입니다. OpenSearch에서는 최대 10,000 차원까지의 임베딩 벡터에 대해서 검색기능을 제공하고 있습니다. </p>
  3164.  
  3165.  
  3166.  
  3167. <p>OpenSearch에서는 3가지 다른 방법의 쿼리 벡터에 대해서 k-NN의 결과를 얻을 수 있는 3가지 다른 방법을 제공 합니다.</p>
  3168.  
  3169.  
  3170.  
  3171. <ol><li><strong>Approximate k-NN</strong><ul><li>첫 번째 방법은 Approximate k-NN입니다. 여러 알고리즘 중 하나를 사용하여 대략적인 k-NN 결과를 쿼리 벡터로 반환합니다.&nbsp;일반적으로 이러한 알고리즘은 더 짧은 대기 시간, 더 작은 메모리 공간 및 더 확장 가능한 검색과 같은 성능 이점이 있습니다. 그러나 인덱싱 속도와 검색 정확도의 성능은 일부 떨어질 수 있다는 단점이 있습니다.</li></ul></li><li><strong>Script Score k-NN</strong><ul><li>두 번째 방법은 Script Score k-NN 입니다. OpenSearch의 Script Score 기능을 확장하여 나타나는 “knn_vector”에 대하여 정확한 k-NN 검색을 수행합니다. 이 방식을 사용하면 인덱스에 있는 벡터의 하위 집합에 대해서 k-NN 검색을 실행할 수 있습니다. 따라서, 존재하는 벡터에 대해서 사전 필터링이 필요할 경우에 이 방식을 사용합니다.</li></ul></li><li><strong>Painless extensions</strong><ul><li>세 번째 방법은 Painless extensions 입니다. 두 번째로 언급 드린 Script Score k-NN에 비하여 쿼리 성능이 약간 느리다는 단점이 존재합니다. 그러나 거리함수를 더 복잡한 상황에서 적용할 수 있다는 장점이 있습니다.</li></ul></li></ol>
  3172.  
  3173.  
  3174.  
  3175. <p>저희는 소속된 커뮤니티와 날짜를 관련한 필터링 조건이 필요하기 때문에 Script Score k-NN을 선택하여 진행했습니다. <em>(복잡하지 않은 조건이기 때문에 속도가 더 빠른 Script Score k-NN 사용)</em> 이를 통해서 소속된 커뮤니티 등록 날짜 등의 조건으로 필터링된 대상에 대한 검색을 수행할 수 있었습니다.</p>
  3176.  
  3177.  
  3178.  
  3179. <ul><li>변경 후 방법<br><img data-attachment-id="3355" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%80%e1%85%b3%e1%84%85%e1%85%b5%e1%86%b7_10_opensearch%e1%84%92%e1%85%aa%e1%86%af%e1%84%8b%e1%85%ad%e1%86%bc%e1%84%8b%e1%85%a8%e1%84%89%e1%85%b5/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?fit=3404%2C1200&amp;ssl=1" data-orig-size="3404,1200" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="그림_10_opensearch활용예시" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?fit=300%2C106&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?fit=1024%2C361&amp;ssl=1" loading="lazy" width="3404" height="1200" class="wp-image-3355" style="width: 800px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=3404%2C1200&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?w=3404&amp;ssl=1 3404w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=300%2C106&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=1024%2C361&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=768%2C271&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=1536%2C541&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=2048%2C722&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=750%2C264&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?resize=1140%2C402&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/그림_10_opensearch활용예시.png?w=3000&amp;ssl=1 3000w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></li></ul>
  3180.  
  3181.  
  3182.  
  3183. <ol><li>유저가 리멤버 커뮤니티에 접속</li><li>MongoDB에서 유저의 임베딩 값을 추출</li><li>유저에게 추천될 수 있는 카테고리의 콘텐츠 임베딩 값들을 추출하여 유저 임베딩 값과</li><li>코사인 유사도를 비교하여 list 형태로 해당 post id들을 반환</li></ol>
  3184.  
  3185.  
  3186.  
  3187. <h2>5-2. 속도 개선 결과</h2>
  3188.  
  3189.  
  3190.  
  3191. <p>MongoDB를 활용하여 임베딩 벡터를 추출할 때 생겼던 병목을 OpenSearch 내에서 한번에 해결함으로써 시간을 대폭 감축할 수 있었습니다. 유저 임베딩을 업데이트하는 부분에 대해서는 NiFi 라고하는 별도의 시스템을 활용하여 구성하였습니다. </p>
  3192.  
  3193.  
  3194.  
  3195. <p>임베딩을 추출하고 유사도를 계산하는 추천 로직에 있어서 평균적으로 <em><strong>0.2 sec</strong></em> 로 결과를 반환하는 API를 생성할 수 있었습니다.</p>
  3196.  
  3197.  
  3198.  
  3199. <p class="has-text-align-center"><img data-attachment-id="3356" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-07-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-10-13-47/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?fit=1182%2C736&amp;ssl=1" data-orig-size="1182,736" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷-2022-11-07-오후-10.13.47" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?fit=300%2C187&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?fit=1024%2C638&amp;ssl=1" loading="lazy" width="1182" height="736" class="wp-image-3356" style="width: 400px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?resize=1182%2C736&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?w=1182&amp;ssl=1 1182w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?resize=300%2C187&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?resize=1024%2C638&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?resize=768%2C478&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?resize=750%2C467&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-07-오후-10.13.47.png?resize=1140%2C710&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  3200.  
  3201.  
  3202.  
  3203. <hr class="wp-block-separator"/>
  3204.  
  3205.  
  3206.  
  3207. <h1>결론</h1>
  3208.  
  3209.  
  3210.  
  3211. <p>구축한 추천 로직을 활용하여 A/B test를 진행했습니다. A/B test를 통해 추천 로직으로 배포된 글과 “최신글 + 인기글(좋아요, 댓글 다수)”의 클릭률을 비교했습니다. 그 결과, 인기글 보단 클릭률이 낮았고 최신글보단 클릭률이 높은 결과가 나타났습니다.</p>
  3212.  
  3213.  
  3214.  
  3215. <p class="has-text-align-center"><img data-attachment-id="3368" data-permalink="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2022-11-08-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-1-57-38/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?fit=1232%2C734&amp;ssl=1" data-orig-size="1232,734" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="스크린샷 2022-11-08 오후 1.57.38" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?fit=300%2C179&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?fit=1024%2C610&amp;ssl=1" loading="lazy" width="1232" height="734" class="wp-image-3368" style="width: 600px;" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?resize=1232%2C734&#038;ssl=1" alt="" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?w=1232&amp;ssl=1 1232w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?resize=300%2C179&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?resize=1024%2C610&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?resize=768%2C458&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?resize=750%2C447&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/11/스크린샷-2022-11-08-오후-1.57.38.png?resize=1140%2C679&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></p>
  3216.  
  3217.  
  3218.  
  3219. <p>좀 더 다양한 변수를 활용한 고도화된 모델에 대한 연구 진행을 검토했으나 내부 사정으로 인해서 추가 연구와 서비스까지는 이어지지는 못했습니다. 그러나 머신러닝 모델에 대한 서비스 적용은 결과 평가에 앞서서 서비스에 어떻게 적용할 것인지를 고민하는 것이 중요하다는 것을 다시 한번 느끼게 해주는 프로젝트 였습니다.</p>
  3220.  
  3221.  
  3222.  
  3223. <p>실제 예시로 여러 추천 알고리즘들을 서비스에 도입 시에는 빠른 업데이트를 이유로 knn 유사도 방식으로 서비스를 제공했다고 합니다. 이처럼 머신러닝을 서비스에 적용하기 위해서는 머신러닝의 성능에 대한 고려와 서비스 제공에 대한 고려를 동시에 하는 것이 중요합니다.</p>
  3224.  
  3225.  
  3226.  
  3227. <p>리멤버 빅데이터 센터 AI Lab에서는 꾸준히 최신 연구를 활용하여 인재 추천 서비스, 광고 추천 서비스, 명함 인식 등 다양한 연구를 수행하고 있습니다. 차후 AI Lab 에서 연구하는 다른 분야를 소개하고 공유하며 찾아뵙도록 하겠습니다.</p>
  3228.  
  3229.  
  3230.  
  3231. <p>궁금하신 사항은 댓글을 통해 문의 부탁드리며 긴 글 읽어주셔서 감사합니다.</p>
  3232.  
  3233.  
  3234.  
  3235. <hr class="wp-block-separator"/>
  3236.  
  3237.  
  3238.  
  3239. <h1>Reference</h1>
  3240.  
  3241.  
  3242.  
  3243. <ul><li>[1] <a href="https://community.rememberapp.co.kr/main">https://community.rememberapp.co.kr/main</a></li><li>[2] <a href="https://aws.amazon.com/ko/what-is/opensearch/"></a><a href="https://aws.amazon.com/ko/what-is/opensearch/">https://aws.amazon.com/ko/what-is/opensearch/</a></li><li>[3] opensearch knn documentation.. <a style="font-family: &quot;Helvetica Neue&quot;, Helvetica, Roboto, Arial, sans-serif;" href="https://opensearch.org/docs/latest/search-plugins/knn/index/">https://opensearch.org/docs/latest/search-plugins/knn/index/</a></li><li>[4] <a style="font-family: &quot;Helvetica Neue&quot;, Helvetica, Roboto, Arial, sans-serif;" href="https://opensearch.org/blog/odfe-updates/2020/04/Building-k-Nearest-Neighbor-(k-NN)-Similarity-Search-Engine-with-Elasticsearch/">https://opensearch.org/blog/odfe-updates/2020/04/Building-k-Nearest-Neighbor-(k-NN)-Similarity-Search-Engine-with-Elasticsearch/</a></li><li>[5] MongoDB documentation, <a href="https://www.mongodb.com/docs/"></a><a href="https://www.mongodb.com/docs/">https://www.mongodb.com/docs/</a></li><li>[6] Transformer, Vaswani, Ashish, et al. &#8220;Attention is all you need.&#8221;&nbsp;<em>Advances in neural information processing systems</em> 30 (2017).</li><li>[7] Devlin, Jacob, et al. &#8220;Bert: Pre-training of deep bidirectional transformers for language understanding.&#8221;&nbsp;<em>arXiv preprint arXiv:1810.04805</em>&nbsp;(2018).</li><li>[8] SimCSE, Gao, Tianyu, Xingcheng Yao, and Danqi Chen. &#8220;Simcse: Simple contrastive learning of sentence embeddings.&#8221;&nbsp;<em>arXiv preprint arXiv:2104.08821</em>&nbsp;(2021).</li></ul>
  3244. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/">추천 시스템 서비스 적용을 위한 Elastic Search 도입기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  3245. ]]></content:encoded>
  3246. <wfw:commentRss>https://blog.dramancompany.com/2022/11/%ec%b6%94%ec%b2%9c-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%a0%81%ec%9a%a9%ec%9d%84-%ec%9c%84%ed%95%9c-elastic-search-%eb%8f%84%ec%9e%85%ea%b8%b0/feed/</wfw:commentRss>
  3247. <slash:comments>1</slash:comments>
  3248. <post-id xmlns="com-wordpress:feed-additions:1">3343</post-id> </item>
  3249. <item>
  3250. <title>유저 목록을 Redis Bitmap 구조로 저장하여 메모리 절약하기</title>
  3251. <link>https://blog.dramancompany.com/2022/10/%ec%9c%a0%ec%a0%80-%eb%aa%a9%eb%a1%9d%ec%9d%84-redis-bitmap-%ea%b5%ac%ec%a1%b0%eb%a1%9c-%ec%a0%80%ec%9e%a5%ed%95%98%ec%97%ac-%eb%a9%94%eb%aa%a8%eb%a6%ac-%ec%a0%88%ec%95%bd%ed%95%98%ea%b8%b0/</link>
  3252. <comments>https://blog.dramancompany.com/2022/10/%ec%9c%a0%ec%a0%80-%eb%aa%a9%eb%a1%9d%ec%9d%84-redis-bitmap-%ea%b5%ac%ec%a1%b0%eb%a1%9c-%ec%a0%80%ec%9e%a5%ed%95%98%ec%97%ac-%eb%a9%94%eb%aa%a8%eb%a6%ac-%ec%a0%88%ec%95%bd%ed%95%98%ea%b8%b0/#comments</comments>
  3253. <dc:creator><![CDATA[노아론]]></dc:creator>
  3254. <pubDate>Fri, 07 Oct 2022 06:42:32 +0000</pubDate>
  3255. <category><![CDATA[Tech]]></category>
  3256. <category><![CDATA[Redis]]></category>
  3257. <category><![CDATA[구조개선]]></category>
  3258. <category><![CDATA[리멤버]]></category>
  3259. <category><![CDATA[서버]]></category>
  3260. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3201</guid>
  3261.  
  3262. <description><![CDATA[<p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/10/%ec%9c%a0%ec%a0%80-%eb%aa%a9%eb%a1%9d%ec%9d%84-redis-bitmap-%ea%b5%ac%ec%a1%b0%eb%a1%9c-%ec%a0%80%ec%9e%a5%ed%95%98%ec%97%ac-%eb%a9%94%eb%aa%a8%eb%a6%ac-%ec%a0%88%ec%95%bd%ed%95%98%ea%b8%b0/">유저 목록을 Redis Bitmap 구조로 저장하여 메모리 절약하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  3263. ]]></description>
  3264. <content:encoded><![CDATA[ <div data-elementor-type="wp-post" data-elementor-id="3201" class="elementor elementor-3201">
  3265. <div class="elementor-inner">
  3266. <div class="elementor-section-wrap">
  3267. <section class="elementor-section elementor-top-section elementor-element elementor-element-36c5e97 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="36c5e97" data-element_type="section">
  3268. <div class="elementor-container elementor-column-gap-default">
  3269. <div class="elementor-row">
  3270. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4514e6a" data-id="4514e6a" data-element_type="column">
  3271. <div class="elementor-column-wrap">
  3272. <div class="elementor-widget-wrap">
  3273. </div>
  3274. </div>
  3275. </div>
  3276. </div>
  3277. </div>
  3278. </section>
  3279. <section class="elementor-section elementor-top-section elementor-element elementor-element-37177034 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="37177034" data-element_type="section">
  3280. <div class="elementor-container elementor-column-gap-default">
  3281. <div class="elementor-row">
  3282. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b53c9e0" data-id="b53c9e0" data-element_type="column">
  3283. <div class="elementor-column-wrap elementor-element-populated">
  3284. <div class="elementor-widget-wrap">
  3285. <div class="elementor-element elementor-element-5cfe99e9 elementor-widget elementor-widget-text-editor" data-id="5cfe99e9" data-element_type="widget" data-widget_type="text-editor.default">
  3286. <div class="elementor-widget-container">
  3287. <div class="elementor-text-editor elementor-clearfix">
  3288. <p><!-- wp:jetpack/markdown {"source":"안녕하세요, 리멤버 플랫폼 서버 파트의 노아론입니다. \n이번 글에서는 특정 유저군을 타겟팅하는 과정에서 Redis의 SET 구조 대신 Bitmap 구조를 이용하여 어떻게 메모리를 절약할 수 있었는지에 대해 이야기하려고 합니다.\n\n[리멤버 리서치](https://survey.rememberapp.co.kr/)에선 설문 조건에 맞는 유저를 타겟팅하여 응답을 수집하고, 참여한 유저에겐 소정의 리워드를 지급하고 있습니다. \n특정 유저에게 맞는 설문만을 제공하기 위하여 내부의 타겟 시스템을 이용해 설문마다 참여할 수 있는 유저의 고유 ID를 보관하고 있습니다. \n\n이 과정에서 Redis에는 설문에 참여할 수 있는 유저 ID 목록을 SET 구조로 저장하였는데요, \n 보관해야 하는 유저의 수에 비해서 Redis에서 차지하는 메모리 크기가 지나치게 비대한 문제가 있었습니다.\n\n\n## 리멤버 리서치에서는 Redis를 이렇게 사용합니다.\n\n리서치 운영을 위한 사내 어드민 페이지에서 설문 생성을 마치면 지정된 조건에 맞는 유저의 고유 ID를 가져오고,\n설문 대상이 되는 유저 목록은 리멤버 내의 광고 서버에 요청하여 가져오고 있습니다\n\n![리멤버 리서치 서버의 구조] \n\n리서치 서버는 원하는 세부 조건에 맞게 타겟팅 된 유저 고유 ID 목록을 광고서버에 요청하여 데이터를 가져옵니다.\n이렇게 가져온 설문 대상 유저 목록은 Redis에 저장되고 특정 유저가 설문의 대상인지 판별하는 용도로 데이터를 이용하게 됩니다.\n\nRedis에 대상 유저를 저장하는 용도로 채택한 이유로는 아래와 같습니다.\n- 대상 유저 ID 목록의 크기는 적게는 수십명에서 많게는 수십만, 수백만의 단위로 구성됩니다. 유저 목록에 대한 데이터는 광고 서버에서 보존하고 있으므로, 대량의 크기를 가지는 정보를 다른 서비스의 DB에 다시 저장하는 작업은 피하였습니다.\n\n- 대상 유저 ID 목록은 설문이 종료된 뒤에 다시 사용하지 않는 정보입니다. Time-to-live를 어플리케이션 레이어에서 구현하지 않고, Redis 내에서 처리할 수 있습니다.\n\n\n\n## 마주한 상황\n\n유저 ID 목록을 Redis에 저장하는 과정에서 우려되는 지점을 발견하였습니다.\n개발 당시 유저 ID를 Redis에 저장하는 방식으로는 다음 그림과 같이 SET 구조를 사용하였습니다.\n\n![survey:설문ID:target-user-ids 키가 SET 자료구조를 가지고 저장된다](https://blog.dramancompany.com/wp-content/uploads/2022/10/diagram_redis-survey-survey_id-target-user-ids.png)\n\n처음 설문을 생성하고 유저 5천명에게 타겟팅하였습니다. 이때 아래의 과정으로 유저 ID 5천개를 가지고 있는 SET이 추가됩니다.\n![](https://blog.dramancompany.com/wp-content/uploads/2022/10/redis-sadd-survey1target-user-ids.png)\n\n\n이 설문에서 어떤 유저가 참여 대상인지 알기 위해 총 298,456 Byte 크기의 메모리를 소모하였습니다.\n![](https://blog.dramancompany.com/wp-content/uploads/2022/10/redis-survey1targetuser_ids-2.png)\n\n유저의 수가 상대적으로 적거나 동시 진행 중인 설문이 몇가지 되지 않는 상황에서는 천 단위의 유저 ID를 저장하는 상황은 당장 문제가 없어보입니다.\n하지만 수십만명에 달하는 유저의 참여 가능 여부를 보관해야하는 상황이라면 이야기가 달라집니다.\n\n\n\n두번째 설문에서는 유저 19만명에게 타겟팅하고, 얼만큼의 메모리가 소모되었는지 확인해보겠습니다.\n동일하게 타겟팅한 유저의 양만큼 SET이 추가됩니다\n![](https://blog.dramancompany.com/wp-content/uploads/2022/10/redis-sadd-survey2target-user-ids.png)\n\n\n이때 약 10439.65 KB (10.6902 MB)의 메모리가 소모됩니다.\n![19만명일때 SCARD로 188608을, MEMORY USAGE로 10690200을 결과로 받은 이미지](https://blog.dramancompany.com/wp-content/uploads/2022/10/redis-memory_usage-survey2target-user-ids.png)\n\n19만명의 유저의 참여 정보를 저장하기 위해서 약 10MB에 달하는 메모리를 사용한다는 것은 문제가 될 것으로 우려하였습니다.\n수 백만명을 대상으로 하는 설문 10개가 동시에 진행된다면 오로지 유저 목록을 담기 위해 사용하는 Redis의 메모리 크기만해도 기가바이트 단위가 될 것을 짐작할 수 있습니다.\n\n이러한 상황을 초래하게 만들지 않고자, 메모리 크기를 줄이기 위해 Redis의 Bitmap 구조를 고려하였습니다\nRedis Bitmap은 이진 벡터와 같이 사용할 수 있는 String 자료형에서 확장된 것으로, 정수 0부터 N으로 구성된 형태의 SET을 효율적으로 표현할 수 있습니다.\n\n\n## Redis Bitmap 구조를 이용해 개선 시도하기\n\n\n특정 유저가 설문에 참여 가능한지 정보를 알 수 있어야 하므로, 아래 명령어처럼 Bit 오프셋을 유저의 ID로 사용하였고, Redis의 `GETBIT` 커맨드를 통해 오프셋 위치에 저장되는 Bit 값을 설문 참여 가능 대상 유저 여부로 사용하였습니다.\n\n![](https://blog.dramancompany.com/wp-content/uploads/2022/10/redis-bitmap-survey3target-user-ids.png)\n\n성능 면에선 SET 구조에서 사용할 수 있는 커맨드인 SISMEMBER의 시간복잡도는 O(1),\nBitmap 구조의 String 값에서 가능한 커맨드인 GETBIT의 시간복잡도 또한 O(1) 으로\n두 명령 모두 저장된 크기에 따른 성능 차이는 발생하지 않는 것으로 확인하였습니다.\n\nBitmap 구조로 변경하였을 때 메모리 크기는 어느정도 개선할 수 있었는지 보겠습니다.\n![](https://blog.dramancompany.com/wp-content/uploads/2022/10/redis_memory_usage_chart.png)\n\n가장 큰 유저 ID가 50만이면서 50만명에 대한 참여 정보를 담는다면\nSET 구조에선 20,194,504 Byte가, Bitmap 구조에선 114,768 Byte가 필요합니다.\n만일 큰 유저 ID가 75만이고, 이들 75만명에 대한 참여 정보를 담는 경우엔\nSET 구조에선 36,583,112 Byte가, Bitmap 구조에선 114,768 Byte가 필요하게 됩니다.\n\n우려되었던 메모리 크기의 문제를 SET 구조에서 Bitmap 구조로 변경하여 크게 절감할 수 있었습니다. \n\n\n\n\n\n## 마무리\n\n리멤버 리서치의 유저 타겟팅 과정에서 Redis Bitmap 구조를 이용한 것은 상수 시간의 시간 복잡도를 가지면서 차지하는 메모리는 절약하는데 이점을 얻었습니다. 그렇지만, Bitmap 구조가 모든 상황에서 좋은 것이 아니라는 점은 주의해야합니다.\n\n상대적으로 큰 오프셋을 가지며 적은 갯수의 데이터를 보관한다면 Bitmap보다 SET에 저장할 때에 차지하는 메모리 크기가 더 작습니다.\n최대 유저 ID가 1백만이면서 유저 10명의 대상 여부를 저장하는 경우가 이러한 경우입니다.\n수십 혹은 수백 단위의 상대적으로 적은 수의 유저가 포함되는 경우엔 SET구조를 함께 사용하도록 고려하는 것이 좋아보입니다.\n\n\n또한, Bitmap 자료 내에서 Bit가 1인 모든 유저의 ID를 구하는 것은 레디스 명령어로서 지원하지 않습니다.\n따라서 이는 Redis의 Lua Scripting을 이용해 해결해야 합니다.\n\n리멤버의 내부 어드민 페이지에서는 설문 참여 대상 유저 목록 조회를 위한 목적으로, Bit 값이 1인 유저 ID 목록에 대해서 Integer 배열을 반환하는 Lua Script를 구현하여 사용하고 있습니다.\n리멤버 리서치에선 특정 유저의 설문 대상 여부를 판별하기 위한 용도로 쓰여 Bitmap 구조가 적합하였고, 속도를 상수 시간 내에 처리하도록 보장하면서 메모리 크기에서도 많은 이점을 가질 수 있었습니다.\n\n\n글의 마무리는 채용 공고로 맺겠습니다.\n리멤버에선 고난도 애플리케이션 개발에서 나오는 어려운 문제의 해결을 즐기는 동료 분을 모시고 있습니다. \n[리멤버 서버 개발자 채용공고](https://hello.remember.co.kr/recruit/server)\n\n\n감사합니다. \n"} --></p>
  3289. <div class="wp-block-jetpack-markdown">
  3290. <p style="text-align: left;">안녕하세요, 리멤버 플랫폼 서버 파트의 노아론입니다.<br />이번 글에서는 특정 유저군을 타겟팅하는 과정에서 Redis의 SET 구조 대신 Bitmap 구조를 이용하여 어떻게 메모리를 절약할 수 있었는지에 대해 이야기하려고 합니다.</p>
  3291. <p><a href="https://survey.rememberapp.co.kr/">리멤버 리서치</a>에선 설문 조건에 맞는 유저를 타겟팅하여 응답을 수집하고, 참여한 유저에겐 소정의 리워드를 지급하고 있습니다.<br />특정 유저에게 맞는 설문만을 제공하기 위하여 내부의 타겟 시스템을 이용해 설문마다 참여할 수 있는 유저의 고유 ID를 보관하고 있습니다.</p>
  3292. <p>이 과정에서 Redis에는 설문에 참여할 수 있는 유저 ID 목록을 SET 구조로 저장하였는데요,<br />보관해야 하는 유저의 수에 비해서 Redis에서 차지하는 메모리 크기가 지나치게 비대한 문제가 있었습니다.</p>
  3293. <p> </p>
  3294. <h2>리멤버 리서치에서는 Redis를 이렇게 사용합니다.</h2>
  3295. <p>리서치 운영을 위한 사내 어드민 페이지에서 설문 생성을 마치면 지정된 조건에 맞는 유저의 고유 ID를 가져오고,<br />설문 대상이 되는 유저 목록은 리멤버 내의 광고 서버에 요청하여 가져오고 있습니다</p>
  3296. <p><img loading="lazy" class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/diagram_survey-api-service-map-2-e1665124468487.png?resize=269%2C359&#038;ssl=1" width="269" height="359" data-recalc-dims="1" /></p>
  3297. <p> </p>
  3298. <p>리서치 서버는 원하는 세부 조건에 맞게 타겟팅 된 유저 고유 ID 목록을 광고서버에 요청하여 데이터를 가져옵니다.<br />이렇게 가져온 설문 대상 유저 목록은 Redis에 저장되고 특정 유저가 설문의 대상인지 판별하는 용도로 데이터를 이용하게 됩니다.</p>
  3299. <p>Redis에 대상 유저를 저장하는 용도로 채택한 이유로는 아래와 같습니다.</p>
  3300. <ul>
  3301. <li>
  3302. <p>대상 유저 ID 목록의 크기는 적게는 수십명에서 많게는 수십만, 수백만의 단위로 구성됩니다.<br />유저 목록에 대한 데이터는 광고 서버에서 보존하고 있으므로, 대량의 크기를 가지는 정보를 다른 서비스의 DB에 다시 저장하는 작업은 피하였습니다.</p>
  3303. </li>
  3304. <li>
  3305. <p>대상 유저 ID 목록은 설문이 종료된 뒤에 다시 사용하지 않는 정보입니다. Time-to-live를 어플리케이션 레이어에서 구현하지 않고, Redis 내에서 처리할 수 있습니다.</p>
  3306. </li>
  3307. </ul>
  3308. <h2> </h2>
  3309. <h2>마주한 상황</h2>
  3310. <p>유저 ID 목록을 Redis에 저장하는 과정에서 우려되는 지점을 발견하였습니다.<br />개발 당시 유저 ID를 Redis에 저장하는 방식으로는 다음 그림과 같이 SET 구조를 사용하였습니다.</p>
  3311. <p><img class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/diagram_redis-survey-survey_id-target-user-ids-1.png?ssl=1" data-recalc-dims="1" /></p>
  3312. <p> </p>
  3313. <p> 설문을 생성하고 유저 5천명에게 타겟팅하였습니다. 이때 아래의 과정으로 유저 ID 5천개를 가지고 있는 SET이 추가됩니다. <img loading="lazy" class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/redis-sadd-survey1target-user-ids.png?resize=550%2C186&#038;ssl=1" alt="" width="550" height="186" data-recalc-dims="1" /></p>
  3314. <p> </p>
  3315. <p>이 설문에서 어떤 유저가 참여 대상인지 알기 위해 총 298,456 Byte 크기의 메모리를 소모하였습니다. <img loading="lazy" class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/redis-survey1targetuser_ids-2.png?resize=550%2C186&#038;ssl=1" alt="" width="550" height="186" data-recalc-dims="1" /></p>
  3316. <p> </p>
  3317. <p>유저의 수가 상대적으로 적거나 동시 진행 중인 설문이 몇가지 되지 않는 상황에서는 천 단위의 유저 ID를 저장하는 상황은 당장 문제가 없어보입니다.<br />하지만 수십만명에 달하는 유저의 참여 가능 여부를 보관해야하는 상황이라면 이야기가 달라집니다.</p>
  3318. <p>두번째 설문에서는 유저 19만명에게 타겟팅하고, 얼만큼의 메모리가 소모되었는지 확인해보겠습니다.<br />동일하게 타겟팅한 유저의 양만큼 SET이 추가됩니다 <img loading="lazy" class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/redis-sadd-survey2target-user-ids.png?resize=550%2C186&#038;ssl=1" alt="" width="550" height="186" data-recalc-dims="1" /></p>
  3319. <p> </p>
  3320. <p>이때 약 10439.65 KB (10.6902 MB)의 메모리가 소모됩니다. <img loading="lazy" class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/redis-memory_usage-survey2target-user-ids.png?resize=550%2C186&#038;ssl=1" alt="19만명일때 SCARD로 188608을, MEMORY USAGE로 10690200을 결과로 받은 이미지" width="550" height="186" data-recalc-dims="1" /></p>
  3321. <p>19만명의 유저의 참여 정보를 저장하기 위해서 약 10MB에 달하는 메모리를 사용한다는 것은 문제가 될 것으로 우려하였습니다.<br />수 백만명을 대상으로 하는 설문 10개가 동시에 진행된다면 오로지 유저 목록을 담기 위해 사용하는 Redis의 메모리 크기만해도 기가바이트 단위가 될 것을 짐작할 수 있습니다.</p>
  3322. <p>이러한 상황을 초래하게 만들지 않고자, 메모리 크기를 줄이기 위해 Redis의 Bitmap 구조를 고려하였습니다.<br />Redis Bitmap은 이진 벡터와 같이 사용할 수 있는 String 자료형에서 확장된 것으로, 정수 0부터 N으로 구성된 형태의 SET을 효율적으로 표현할 수 있습니다.</p>
  3323. <p> </p>
  3324. <h2>Redis Bitmap 구조를 이용해 개선 시도하기</h2>
  3325. <p>특정 유저가 설문에 참여 가능한지 정보를 알 수 있어야 하므로, 아래 명령어처럼 Bit 오프셋을 유저의 ID로 사용하였고,<br />Redis의 <code>GETBIT</code> 커맨드를 통해 오프셋 위치에 저장되는 Bit 값을 설문 참여 가능 대상 유저 여부로 사용하였습니다.</p>
  3326. <p><img loading="lazy" class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/redis-bitmap-survey3target-user-ids.png?resize=550%2C167&#038;ssl=1" alt="" width="550" height="167" data-recalc-dims="1" /></p>
  3327. <p>성능 면에선 SET 구조에서 사용할 수 있는 커맨드인 SISMEMBER의 시간복잡도는 O(1), Bitmap 구조의 String 값에서 가능한 커맨드인 GETBIT의 시간복잡도 또한 O(1) 으로<br />두 명령 모두 저장된 크기에 따른 성능 차이는 발생하지 않는 것으로 확인하였습니다.</p>
  3328. <p>Bitmap 구조로 변경하였을 때 메모리 크기는 어느정도 개선할 수 있었는지 보겠습니다. <img class="aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/10/redis_memory_usage_chart.png?ssl=1" alt="" data-recalc-dims="1" /></p>
  3329. <p>가장 큰 유저 ID가 50만이면서 50만명에 대한 참여 정보를 담는다면 SET 구조에선 20,194,504 Byte, Bitmap 구조에선 114,768 Byte가 필요합니다.<br />만일 가장 큰 유저 ID가 75만이고, 이들 75만명에 대한 참여 정보를 담는 경우엔 SET 구조에선 36,583,112 Byte가, Bitmap 구조에선 114,768 Byte가 필요하게 됩니다.</p>
  3330. <p>우려되었던 메모리 크기의 문제를 SET 구조에서 Bitmap 구조로 변경하여 크게 절감할 수 있었습니다.</p>
  3331. <p> </p>
  3332. <h2>마무리</h2>
  3333. <p>리멤버 리서치의 유저 타겟팅 과정에서 Redis Bitmap 구조를 이용한 것은 상수 시간의 시간 복잡도를 가지면서 차지하는 메모리는 절약하는데 이점을 얻었습니다. <br />그렇지만, Bitmap 구조가 모든 상황에서 좋은 것이 아니라는 점은 주의해야합니다.</p>
  3334. <p>상대적으로 큰 오프셋을 가지며 적은 갯수의 데이터를 보관한다면 Bitmap보다 SET에 저장할 때에 차지하는 메모리 크기가 더 작습니다. <br />최대 유저 ID가 1백만이면서 유저 10명의 대상 여부를 저장하는 경우가 이러한 경우입니다. <br />수십 혹은 수백 단위의 상대적으로 적은 수의 유저가 포함되는 경우엔 SET구조를 함께 사용하도록 고려하는 것이 좋아보입니다.</p>
  3335. <p>또한, Bitmap 자료 내에서 Bit가 1인 모든 유저의 ID를 구하는 것은 레디스 명령어로서 지원하지 않습니다. 따라서 이는 Redis의 Lua Scripting을 이용해 해결해야 합니다.</p>
  3336. <p>리멤버의 내부 어드민 페이지에서는 설문 참여 대상 유저 목록 조회를 위한 목적으로,<br />Bit 값이 1인 유저 ID 목록에 대해서 Integer 배열을 반환하는 Lua Script를 구현하여 사용하고 있습니다. <br />리멤버 리서치에선 특정 유저의 설문 대상 여부를 판별하기 위한 용도로 쓰여 Bitmap 구조가 적합하였고, 속도를 상수 시간 내에 처리하도록 보장하면서 메모리 크기에서도 많은 이점을 가질 수 있었습니다.</p>
  3337. <p>글의 마무리는 채용 공고로 맺겠습니다.<br />리멤버에선 고난도 애플리케이션 개발에서 나오는 어려운 문제의 해결을 즐기는 동료 분을 모시고 있습니다.<br /><strong><a href="https://hello.remember.co.kr/recruit/server">리멤버 서버 개발자 채용공고</a></strong></p>
  3338. <p>감사합니다.</p>
  3339. </div>
  3340. <p><!-- /wp:jetpack/markdown --></p> </div>
  3341. </div>
  3342. </div>
  3343. </div>
  3344. </div>
  3345. </div>
  3346. </div>
  3347. </div>
  3348. </section>
  3349. </div>
  3350. </div>
  3351. </div>
  3352. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/10/%ec%9c%a0%ec%a0%80-%eb%aa%a9%eb%a1%9d%ec%9d%84-redis-bitmap-%ea%b5%ac%ec%a1%b0%eb%a1%9c-%ec%a0%80%ec%9e%a5%ed%95%98%ec%97%ac-%eb%a9%94%eb%aa%a8%eb%a6%ac-%ec%a0%88%ec%95%bd%ed%95%98%ea%b8%b0/">유저 목록을 Redis Bitmap 구조로 저장하여 메모리 절약하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  3353. ]]></content:encoded>
  3354. <wfw:commentRss>https://blog.dramancompany.com/2022/10/%ec%9c%a0%ec%a0%80-%eb%aa%a9%eb%a1%9d%ec%9d%84-redis-bitmap-%ea%b5%ac%ec%a1%b0%eb%a1%9c-%ec%a0%80%ec%9e%a5%ed%95%98%ec%97%ac-%eb%a9%94%eb%aa%a8%eb%a6%ac-%ec%a0%88%ec%95%bd%ed%95%98%ea%b8%b0/feed/</wfw:commentRss>
  3355. <slash:comments>4</slash:comments>
  3356. <post-id xmlns="com-wordpress:feed-additions:1">3201</post-id> </item>
  3357. <item>
  3358. <title>아름다운 코드를 향한 함께하는 여정 &#8211; Part 1</title>
  3359. <link>https://blog.dramancompany.com/2022/08/%ec%95%84%eb%a6%84%eb%8b%a4%ec%9a%b4-%ec%bd%94%eb%93%9c%eb%a5%bc-%ed%96%a5%ed%95%9c-%ed%95%a8%ea%bb%98%ed%95%98%eb%8a%94-%ec%97%ac%ec%a0%95-part-1/</link>
  3360. <comments>https://blog.dramancompany.com/2022/08/%ec%95%84%eb%a6%84%eb%8b%a4%ec%9a%b4-%ec%bd%94%eb%93%9c%eb%a5%bc-%ed%96%a5%ed%95%9c-%ed%95%a8%ea%bb%98%ed%95%98%eb%8a%94-%ec%97%ac%ec%a0%95-part-1/#respond</comments>
  3361. <dc:creator><![CDATA[평호 김]]></dc:creator>
  3362. <pubDate>Thu, 25 Aug 2022 07:05:52 +0000</pubDate>
  3363. <category><![CDATA[Tech]]></category>
  3364. <category><![CDATA[Android]]></category>
  3365. <category><![CDATA[구조개선]]></category>
  3366. <guid isPermaLink="false">https://blog.dramancompany.com/?p=3073</guid>
  3367.  
  3368. <description><![CDATA[<p>리멤버 안드로이드 코드는 클린아키텍처 + MVP 로 되어 있습니다. 하지만 2016년도의 부터 이어진 코드이다 보니 이전에 작성된 코드와 현재에 작성된 코드가 다른 형태를 보이고 있는 경우가 발생 하고 있었습니다. 새롭게 작성 되는 코드는 PR 을 통해서 점점 비슷한 구조로 작성 되고 있지만 더 명확하게 가는게 좋겠다고 생각하여 구조 개선 여정을 시작 했습니다. 구조개선을 위해서 당시 고민 했던 내용을 공유과 어떤 방법으로 진행 한지를 공유하기 하기 위한 내용의 게시글 입니다. 해당 게시글은 아래의 내용들이 있습니다.</p>
  3369. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/08/%ec%95%84%eb%a6%84%eb%8b%a4%ec%9a%b4-%ec%bd%94%eb%93%9c%eb%a5%bc-%ed%96%a5%ed%95%9c-%ed%95%a8%ea%bb%98%ed%95%98%eb%8a%94-%ec%97%ac%ec%a0%95-part-1/">아름다운 코드를 향한 함께하는 여정 &#8211; Part 1</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  3370. ]]></description>
  3371. <content:encoded><![CDATA[ <div data-elementor-type="wp-post" data-elementor-id="3073" class="elementor elementor-3073">
  3372. <div class="elementor-inner">
  3373. <div class="elementor-section-wrap">
  3374. <section class="elementor-section elementor-top-section elementor-element elementor-element-0922f8b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="0922f8b" data-element_type="section">
  3375. <div class="elementor-container elementor-column-gap-default">
  3376. <div class="elementor-row">
  3377. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ef081ce" data-id="ef081ce" data-element_type="column">
  3378. <div class="elementor-column-wrap elementor-element-populated">
  3379. <div class="elementor-widget-wrap">
  3380. <div class="elementor-element elementor-element-590df2c elementor-widget elementor-widget-image" data-id="590df2c" data-element_type="widget" data-widget_type="image.default">
  3381. <div class="elementor-widget-container">
  3382. <div class="elementor-image">
  3383. <img width="1024" height="682" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?fit=1024%2C682&amp;ssl=1" class="attachment-large size-large" alt="" loading="lazy" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?w=2560&amp;ssl=1 2560w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=300%2C200&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=1024%2C682&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=768%2C511&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=1536%2C1022&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=2048%2C1363&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=750%2C499&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?resize=1140%2C759&amp;ssl=1 1140w" sizes="(max-width: 1000px) 100vw, 1000px" data-attachment-id="3101" data-permalink="https://blog.dramancompany.com/2022/08/%ec%95%84%eb%a6%84%eb%8b%a4%ec%9a%b4-%ec%bd%94%eb%93%9c%eb%a5%bc-%ed%96%a5%ed%95%9c-%ed%95%a8%ea%bb%98%ed%95%98%eb%8a%94-%ec%97%ac%ec%a0%95-part-1/together-9/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?fit=2560%2C1704&amp;ssl=1" data-orig-size="2560,1704" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="together-9" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?fit=300%2C200&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/08/together-9-scaled.jpg?fit=1024%2C682&amp;ssl=1" /> </div>
  3384. </div>
  3385. </div>
  3386. </div>
  3387. </div>
  3388. </div>
  3389. </div>
  3390. </div>
  3391. </section>
  3392. <section class="elementor-section elementor-top-section elementor-element elementor-element-1ab75c1b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="1ab75c1b" data-element_type="section">
  3393. <div class="elementor-container elementor-column-gap-default">
  3394. <div class="elementor-row">
  3395. <div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-478ffc6a" data-id="478ffc6a" data-element_type="column">
  3396. <div class="elementor-column-wrap elementor-element-populated">
  3397. <div class="elementor-widget-wrap">
  3398. <div class="elementor-element elementor-element-7333bbea elementor-widget elementor-widget-text-editor" data-id="7333bbea" data-element_type="widget" data-widget_type="text-editor.default">
  3399. <div class="elementor-widget-container">
  3400. <div class="elementor-text-editor elementor-clearfix">
  3401. <p><!-- wp:image --></p>
  3402. <figure class="wp-block-image"><img alt="" /></figure>
  3403. <p><!-- /wp:image --></p>
  3404. <p><!-- wp:paragraph --></p>
  3405. <p>안녕하세요. 리멤버 안드로이드 개발자 김평호 입니다.</p>
  3406. <p><!-- /wp:paragraph --></p>
  3407. <p><!-- wp:paragraph --></p>
  3408. <p>리멤버 안드로이드 코드는 클린아키텍처 + MVP 로 되어 있습니다. 하지만 2016년도의 부터 이어진 코드이다 보니 이전에 작성된 코드와 현재에 작성된 코드가 다른 형태를 보이고 있는 경우가 발생 하고 있었습니다. 새롭게 작성 되는 코드는 PR 을 통해서 점점 비슷한 구조로 작성 되고 있지만 더 명확하게 가는게 좋겠다고 생각하여 구조 개선 여정을 시작 했습니다. 구조개선을 위해서 당시 고민 했던 내용을 공유과 어떤 방법으로 진행 한지를 공유하기 하기 위한 내용의 게시글 입니다. 해당 게시글은 아래의 내용들이 있습니다.</p>
  3409. <p><!-- /wp:paragraph --></p>
  3410. <p><!-- wp:list --></p>
  3411. <ul>
  3412. <li>왜 구조 개선을 생각 하게 되었는지에 대한 고민</li>
  3413. <li>구조 개선은 어떻게 진행 했는지에 대한 내용</li>
  3414. </ul>
  3415. <p><!-- /wp:list --></p>
  3416. <p><!-- wp:paragraph --></p>
  3417. <p><!-- /wp:paragraph --></p>
  3418. <p><!-- wp:heading --></p>
  3419. <h2>왜 우리는 매주 2시간을 함께 연구 하게 되었는가?</h2>
  3420. <p><!-- /wp:heading --></p>
  3421. <p><!-- wp:paragraph --></p>
  3422. <p><strong>인내하며 타협하며 개발</strong></p>
  3423. <p><!-- /wp:paragraph --></p>
  3424. <p><!-- wp:paragraph --></p>
  3425. <p>타협 :</p>
  3426. <p><!-- /wp:paragraph --></p>
  3427. <p><!-- wp:list --></p>
  3428. <ul>
  3429. <li>코드는 클린아키텍처 + MVP 로 개발 되어 있었습니다. 구조 와 패턴이 잘 구현 되고 있고 온보딩 기간의 학습으로 코드에 적응하고 개발하는데는 <strong>큰 </strong>불편함은 없습니다. 코드 리뷰도 기존의 구조 단단하게 하고 유지하는 방향을 가지고 진행 하였습니다. 코드에 적응이 된거라 생각하게 되었고 그 적응 잘못되었다고 생각 하진 않고 있었습니다. 유지보수가 어렵지 않고 새로운 기능 개발하는 속도도 문제 없었습니다.</li>
  3430. </ul>
  3431. <p><!-- /wp:list --></p>
  3432. <p><!-- wp:paragraph --></p>
  3433. <p><!-- /wp:paragraph --></p>
  3434. <p><!-- wp:paragraph --></p>
  3435. <p>인내:</p>
  3436. <p><!-- /wp:paragraph --></p>
  3437. <p><!-- wp:list --></p>
  3438. <ul>
  3439. <li>학습에 필요한 샘플을 보면 거의 대부분이 MVVM 으로 작성 되어 있어 과거(MVP)와 현재(MVVM) 라고 생각 될때가 많았습니다. 파트원 모두 MVVM 으로 과제를 진행 해 주셔서 개념과 사용에 대해서 알고 있지만 장시간 MVP 코드를 보다 보니 MVVM 을 유니콘 처럼 생각 하는 느낌을 많이 받게 되었습니다.</li>
  3440. <li>파트시간에 안드로이드 기술에 대한 다양한 학습 시간을 만들면서 문제가 있다고 생각을 전환 하였습니다. 파트에서는 매주 2시간정도의 시간을 이용해서 새로운 기술 또는 기존에 사용하는 기술을 깊게 학습하고 있습니다. 새로운 기술은 이론 학습, 샘플 생성, 리멤버 코드에 적용후 장단점 파악 하는 형태로 진행 하고 있습니다. 리멤버 코드에 학습한 기술이 적용되지 않고 학습으로 끝나는 경우가 발생하기 시작 했습니다.</li>
  3441. <li>Dagger 사용 에 대한 어색함은 처음 부터 있었지만 사용 하다 보면 편하다는 이유로 같은 방식으로 사용하고 있습니다. Dagger 처음 학습 할때와 실제 리멤버 코드에서 사용은 다르게 보입니다.</li>
  3442. <li>요구 조건 변화에 유연하게 대응하고 재 사용을 늘리기 위해서 클린 아키텍처와 MVP 는 발전 시키며 개발을 진행 하고 있습니다.</li>
  3443. </ul>
  3444. <p><!-- /wp:list --></p>
  3445. <p><!-- wp:paragraph --></p>
  3446. <p><!-- /wp:paragraph --></p>
  3447. <p><!-- wp:paragraph --></p>
  3448. <p>결론</p>
  3449. <p><!-- /wp:paragraph --></p>
  3450. <p><!-- wp:list --></p>
  3451. <ul>
  3452. <li>우리는 모두 클린아키텍처 + MVVM + Hilt 를 사용하고 싶다. 기술 부채를 계속 쌓아가지 않고 새롭게 추가되는 화면이라도 원하는 방향으로 개발하고 싶다 였습니다.</li>
  3453. </ul>
  3454. <p><!-- /wp:list --></p>
  3455. <p><!-- wp:heading {"level":6} --></p>
  3456. <h6><strong>그래서 구조 개선을 결정</strong></h6>
  3457. <p><!-- /wp:heading --></p>
  3458. <p><!-- wp:list --></p>
  3459. <ul>
  3460. <li>구조 개선을 결정하고 많은 고민이 시작 되었습니다. 파트원은 모두 각각의 목적 조직에서 업무를 진행하고 있어서 해당 일을 전담 할 수 있는 인력이 없었습니다. 만약 전담할 인력이 있다고 하더라도 혼자서는 너무 힘든 일이라는 생각이 들었습니다. 여러사람의 의견을 모아서 작업을 해야 할거고 많은 의견 충돌이 있을거라 예상하고 있었기 때문입니다.게다가 우리가 생각 하는 클린아키텍처+ MVVM 은 동일한 내용이 맞을까도 생각 하게 되었습니다. 수많은 생각을 하다가 문득 같은 &#8220;팀&#8221; 이라는게 떠 올랐습니다. 한개의 repository 에서 함께 개발하는 구성원들이라는 생각이 들었고 <strong>&#8220;함께&#8221;</strong> 라는 용어가 생각 이 났습니다. 단순한 단어가 많은 생각을 정리 할 수 있게 도와 주었습니다.</li>
  3461. </ul>
  3462. <p><!-- /wp:list --></p>
  3463. <p><!-- wp:paragraph --></p>
  3464. <p><!-- /wp:paragraph --></p>
  3465. <p><!-- wp:heading --></p>
  3466. <h2>&#8220;함께 하는 여정&#8221;</h2>
  3467. <p><!-- /wp:heading --></p>
  3468. <p><!-- wp:list --></p>
  3469. <ul>
  3470. <li>우리는 같은 파트에서 함께 개발하는 동료라고 생각하고 모두가 만족하는 코드를 향해 간다고 생각하니 결론에 쉽게 도달 할 수 있었습니다.</li>
  3471. <li>파트원 모두는 아름다운 코드를 만들기 위해 노력 하고 있지만 각자의 생각이 다르기 때문에 파편 화가 되어 간다. 그러면 최종적으로 생각하는 코드를 협의해서 함께 만들어 가면 되겠다는 결론을 내렸습니다.</li>
  3472. <li>협의하는 시간을 강제적으로 매주 만들어서 이야기하면 해결이 될거 같았습니다.</li>
  3473. <li>레거시 처리는 앞으로 작성하는 코드에 대한 대비, 그리고 정말 레거시 코드에 대한 리팩토링이 있다고 생각합니다. 저는 구 버전에 있는 레거시 코드보다 현재 작성하고 있는 코드에 대한 내용을 만들어 가는게 중요하다고 생각해서 우리 모두가 만족 하는 구조를 함께 만들어 보기로 했습니다.</li>
  3474. <li>회의 시간도 딱딱 하지 않게 아름다운 코드를 위한 대화의 시간으로 “<strong>뷰티톡</strong>“ 으로 시간을 정하고 2021년12월 부터 일정을 시작 했습니다.</li>
  3475. </ul>
  3476. <p><!-- /wp:list --></p>
  3477. <p><!-- wp:paragraph --></p>
  3478. <p>중요: 함께 발전 시킬 수 있습니다. 안드로이드 개발자 채용 중입니다. <a href="https://hello.remember.co.kr/recruit/android">Android 개발자</a></p>
  3479. <p><!-- /wp:paragraph --></p>
  3480. <p><!-- wp:paragraph --></p>
  3481. <p><!-- /wp:paragraph --></p>
  3482. <p><!-- wp:heading {"level":4} --></p>
  3483. <h4><strong>&#8220;함께 시작 된 뷰티톡 6개월의 시간&#8221;</strong></h4>
  3484. <p><!-- /wp:heading --></p>
  3485. <p><!-- wp:list --></p>
  3486. <ul>
  3487. <li>시작
  3488. <ul>
  3489. <li>어떻게 시작 할지 고민이 많았습니다. 시작을 잘 풀어야 앞으로 회의 시간이 일방 적이지 않고 다양한 의견을 함께 나누는 시간이 될거라 예상 했습니다.</li>
  3490. <li>처음은 역시 서로의 생각을이야기 할 수 있게 각자가 생각 하는 “클린아키텍처“의 구조를 발표 하는 시간으로 정했습니다. 파트원 4명 모두가 자신이 생각하는 구조를 그려오고 간단하게 설명하고 질문을 받는 시간으로 가졌습니다. 4명 모두가 발표가 끝나고 “클린아키텍처“에 대해 논의를 하면서 다른 부분을 이야기 하며 다른 부분을 이해하고 통일화 하는 시간으로 일정을 시작 했습니다.</li>
  3491. </ul>
  3492. </li>
  3493. <li>진행
  3494. <ul>
  3495. <li>통일된 “클린아키텍처” 개념을 모두가 동일한 내용으로 맞추니 다음으로 할일은 실제 패키지, 모듈 등을 어떻게 할지에 대한 내용을 찾아서 하나씩 진행하게 되었습니다.</li>
  3496. <li>이상적인 내용으로 dummy 코드를 생성하는것 보다 현재 동작 하고 있는 화면을 우리가 생각하는 구조로 만들기로 결정 했습니다.</li>
  3497. </ul>
  3498. </li>
  3499. <li>내용 :
  3500. <ul>
  3501. <li>모듈 분리</li>
  3502. <li>DataBinding 추가 및 MVVM 사용</li>
  3503. <li>UseCase 사용</li>
  3504. <li>Dagger -&gt; Hilt 로 변경</li>
  3505. <li>Rx 버전 업데이트 및 사용 방법</li>
  3506. <li>응답 객체와 Entity 객체 분리</li>
  3507. <li>신규 화면 생성시 해당 구조 사용을 권장</li>
  3508. </ul>
  3509. </li>
  3510. <li>결과 :
  3511. <ul>
  3512. <li>구조와 샘플 까지 작성하는데 6개월 이라는 시간이 걸렸지만 행복한 시간이었습니다. 서로의 의견을 조율하고 이야기 하는 시간 모두가 좋았습니다. 운용 되고 있는 코드에서 통합된 구조를 만들다 보니 다양한 상황에 직면 하게 되었지만 함께 해결해 나가고 최종 화면 보일때 파트의 승리라 생각 했습니다.</li>
  3513. <li>현재 우리가 만족 하는 클린아키텍처 의 MVVM 코드를 사용 할 것이고 이어 나갈 것이다. 함께 하는 시간의 힘이고 노력이다. 다같이 협의한 내용이고 만족 있습니다. 설계는 정답이 없다고 생각하기에 기본적인 구조에 맞게, 회사 상황에 맞게, 변형하고 재 조립 이라고 생각합니다. 그래서 우리만의 설계를 만들어 가고 있고 앞으로도 계속 발전 시킬 예정입니다.<br /><br />우리와 함께할 파트원을 채용 중입니다. <a href="https://hello.remember.co.kr/recruit/android">Android 개발자</a></li>
  3514. </ul>
  3515. </li>
  3516. </ul>
  3517. <p><!-- /wp:list --></p>
  3518. <p><!-- wp:paragraph --></p>
  3519. <p><br />다음편: 안드로이드 파트에서 진행한 구조를 적용하기</p>
  3520. <p><!-- /wp:paragraph --></p>
  3521. <p><!-- wp:heading {"level":3} --></p>
  3522. <h3><br />여기서 잠깐</h3>
  3523. <p><!-- /wp:heading --></p>
  3524. <p><!-- wp:paragraph --></p>
  3525. <p>잠시 가장 적용 하고 싶었던 것중 하나인 MVVM 도입을 결정하게 된 내용을 조금 이야기하고 넘어가 보겠습니다. 레거시 리멤버의 코드의 구조에 대한 내용을 포함 하고 싶어서 입니다.</p>
  3526. <p><!-- /wp:paragraph --></p>
  3527. <p><!-- wp:paragraph --></p>
  3528. <p><strong>패턴 사용의 파편 화 </strong></p>
  3529. <p><!-- /wp:paragraph --></p>
  3530. <p><!-- wp:list --></p>
  3531. <ul>
  3532. <li>같은 구조를 목표로 개발 하고 있지만 각각의 이해도가 다르고 사용하면서 조금 씩 발전하고 있어서 파편 화가 진행이 되고 있습니다. 구조에 대한 파편 화는 초기 MVP, 향상 된 MVP, UseCase 사용의 추가등 조금씩 진행 되었고 시간이 지남에 따라 차이가 커지고 있습니다. 아래 내용은 점차 파편화 되어가는 코드를 개략적으로 보여주는 내용입니다.</li>
  3533. </ul>
  3534. <p><!-- /wp:list --></p>
  3535. <p><!-- wp:paragraph --></p>
  3536. <p><!-- /wp:paragraph --></p>
  3537. <p><!-- wp:list --></p>
  3538. <ul>
  3539. <li>초기 MVP:
  3540. <ul>
  3541. <li>코드중 일부가 아래 처럼 사용자가 동작을 하면 presenter.updateName 호출하고 presenter 에서는 API 사용을 위한 비동기 처리와 간단한 예외만 처리 하고 있었습니다. (2016년도 정도의 코드 형태이고 이해를 돕기 위해 작성된 내용입니다.</li>
  3542. </ul>
  3543. </li>
  3544. </ul>
  3545. <p><!-- /wp:list --></p>
  3546. <p><!-- wp:code --></p>
  3547. <pre class="wp-block-code"><code>// activity 코드
  3548. override fun onCreate(savedInstanceState: Bundle?) {
  3549.   super.onCreate(savedInstanceState)
  3550.    binding = ActivityCommunityBinding.inflate(layoutInflater)
  3551.    setContentView(binding.root)
  3552.  
  3553.    initCommunity()
  3554.    presenter.loadCommunityList(argument.communityId)        
  3555. }
  3556.  
  3557. private fun initCommunity() {
  3558.    this.communityId = communityId
  3559.    binding.appBar.title = R.string.community_title
  3560.    binding.communityName.setOnClickListener {
  3561.        ...
  3562.    }
  3563. }
  3564.  
  3565. // presenter 코드
  3566. fun loadCommunityList(  communityId: Long) {
  3567.    //api call
  3568. }</code></pre>
  3569. <p><!-- /wp:code --></p>
  3570. <p><!-- wp:list --></p>
  3571. <ul>
  3572. <li>향상된 MVP
  3573. <ul>
  3574. <li>kotlin 으로 작성하는 시기의 MVP 코드의 형태가 변화 하였습니다.</li>
  3575. </ul>
  3576. <ul>
  3577. <li>activity, fragment 에서 발생하는 모든 이벤트(사용자 액션 포함 )는 presenter 로 전달하고 모든 비즈니스 로직은 presenter 에서 처리 하는 개념으로 처리하고 있습니다. presenter 에서는 ‘view.setCommunityName(&#8220;커뮤니티 이름&#8221;)’ 처럼 각각의 view 하나 하나를 설정 하도록 개발 하고 있습니다.</li>
  3578. </ul>
  3579. </li>
  3580. </ul>
  3581. <p><!-- /wp:list --></p>
  3582. <p><!-- wp:code --></p>
  3583. <pre class="wp-block-code"><code>// activity 코드
  3584. override fun onCreate(savedInstanceState: Bundle?) {
  3585.  super.onCreate(savedInstanceState)
  3586.  binding = ActivityCommunityBinding.inflate(layoutInflater)
  3587.  setContentView(binding.root)
  3588.  
  3589.  val argument: Argument = intent.getParcelableExtra(COMMUNITY_ACTIVITY_INTENT_KEY) ?: let {
  3590.    finish()
  3591.    return
  3592.  }
  3593.  
  3594.  presenter.onCreate(
  3595.    argument.communityId,
  3596.    argument.community,
  3597.    argument.boardId
  3598.  )        
  3599. }
  3600.  
  3601. // presenter 코드
  3602. fun onCreate(
  3603.  communityId: Long,
  3604.  community: Community?,
  3605.  boardId: Long?
  3606. ) {
  3607.    this.communityId = communityId
  3608.    view.setAppbarTitle(R.string.community_title)
  3609.    view.setCommunityNameClickListener {
  3610.        view.goToCommunity(communityId)
  3611.    }
  3612.    view.setCommunityName("커뮤니티 이름")
  3613.    loadCommunityList(communityId)
  3614.    ...
  3615. }
  3616.  
  3617. fun onClickFromCommunityName() {
  3618.   view.goToCommunity()
  3619. }</code></pre>
  3620. <p><!-- /wp:code --></p>
  3621. <p><!-- wp:list --></p>
  3622. <ul>
  3623. <li>클린아키텍처의 UseCase 사용
  3624. <ul>
  3625. <li>repository 의 helper 를 만들어서 useCase 처럼 사용 했지만 새롭게 입사하신 분들은 생소하게 보일 수 있습니다.</li>
  3626. </ul>
  3627. <ul>
  3628. <li>useCase 도입을 하기로 결정 했지만 파트에서 생각하는 useCase 내용이 다르고 구현하는 방법도 다양하게 되었습니다.</li>
  3629. </ul>
  3630. </li>
  3631. <li>결국 맞춰 가는 시간의 부족
  3632. <ul>
  3633. <li>PR을 통해서 코딩컨벤션을 맞추고 이야기를 했지만 아쉬운 느낌이 많았습니다. PR 전에 구조가 잡혀 있었다면, 컨벤션이 잘 정의 되어 있었다면 이런 생각이 많이 졌습니다.</li>
  3634. <li>드라마앤컴퍼니 조직 구조가 미션 조직 형태의 “Crew” 로 분리 되어 있다 보니 파트가 함께 하는 시간이 부족하여 구조 개선이라는 큰 방향에 대한 처리는 어떻게 해야 할 지 방법을 찾지 못 했습니다.</li>
  3635. <li>그래서 찾은 결론이 일주일에 최소 2시간 씩이라도 함게 하는시간을 만들어 발전 시키는 방향을 생각 하게 되었습니다.</li>
  3636. </ul>
  3637. </li>
  3638. </ul>
  3639. <p><!-- /wp:list --></p> </div>
  3640. </div>
  3641. </div>
  3642. </div>
  3643. </div>
  3644. </div>
  3645. </div>
  3646. </div>
  3647. </section>
  3648. </div>
  3649. </div>
  3650. </div>
  3651. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/08/%ec%95%84%eb%a6%84%eb%8b%a4%ec%9a%b4-%ec%bd%94%eb%93%9c%eb%a5%bc-%ed%96%a5%ed%95%9c-%ed%95%a8%ea%bb%98%ed%95%98%eb%8a%94-%ec%97%ac%ec%a0%95-part-1/">아름다운 코드를 향한 함께하는 여정 &#8211; Part 1</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  3652. ]]></content:encoded>
  3653. <wfw:commentRss>https://blog.dramancompany.com/2022/08/%ec%95%84%eb%a6%84%eb%8b%a4%ec%9a%b4-%ec%bd%94%eb%93%9c%eb%a5%bc-%ed%96%a5%ed%95%9c-%ed%95%a8%ea%bb%98%ed%95%98%eb%8a%94-%ec%97%ac%ec%a0%95-part-1/feed/</wfw:commentRss>
  3654. <slash:comments>0</slash:comments>
  3655. <post-id xmlns="com-wordpress:feed-additions:1">3073</post-id> </item>
  3656. <item>
  3657. <title>리멤버는 서비스 모니터링을 어떻게 하고 있을까?</title>
  3658. <link>https://blog.dramancompany.com/2022/06/how-remember-monitors/</link>
  3659. <comments>https://blog.dramancompany.com/2022/06/how-remember-monitors/#comments</comments>
  3660. <dc:creator><![CDATA[이 한별]]></dc:creator>
  3661. <pubDate>Tue, 21 Jun 2022 07:47:32 +0000</pubDate>
  3662. <category><![CDATA[Tech]]></category>
  3663. <category><![CDATA[AWS]]></category>
  3664. <category><![CDATA[Rails]]></category>
  3665. <category><![CDATA[ruby]]></category>
  3666. <category><![CDATA[Ruby on Rails]]></category>
  3667. <category><![CDATA[리멤버]]></category>
  3668. <guid isPermaLink="false">https://blog.dramancompany.com/?p=2967</guid>
  3669.  
  3670. <description><![CDATA[<p>안녕하세요? 리멤버를 서비스하고 있는 드라마앤컴퍼니의 플랫폼 서버 파트 테크리드 이한별 ⭐ 입니다. 😂 리멤버는 명함 관리부터 시작하여 인재 검색(다이렉트 소싱), 채용 공고, 헤드헌팅을 비롯한 채용 사업 뿐 아니라 주요 경제 소식을 매일 큐레이션 및 정리해주는 리멤버 나우, 회원들끼리 직장 관련 고민을 털어놓고 해결하기 위한 리멤버 커뮤니티, 전국의 일하는 사람들에게 설문 조사를 가능하게 한 리멤버 서베이 [&#8230;]</p>
  3671. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/06/how-remember-monitors/">리멤버는 서비스 모니터링을 어떻게 하고 있을까?</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  3672. ]]></description>
  3673. <content:encoded><![CDATA[
  3674. <p style="font-size:16px">안녕하세요? 리멤버를 서비스하고 있는 드라마앤컴퍼니의 플랫폼 서버 파트 테크리드 이한별 <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 입니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f602.png" alt="😂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  3675.  
  3676.  
  3677.  
  3678. <p style="font-size:16px">리멤버는 명함 관리부터 시작하여 인재 검색(다이렉트 소싱), 채용 공고, 헤드헌팅을 비롯한 채용 사업 뿐 아니라 주요 경제 소식을 매일 큐레이션 및 정리해주는 리멤버 나우, 회원들끼리 직장 관련 고민을 털어놓고 해결하기 위한 리멤버 커뮤니티, 전국의 일하는 사람들에게 설문 조사를 가능하게 한 리멤버 서베이 등 다양한 서비스를 하고 있습니다.</p>
  3679.  
  3680.  
  3681.  
  3682. <p style="font-size:16px">다양한 서비스를 하고 있고, 대규모 트래픽을 안정적으로 잘 처리할 수 있으려면 개발자로서 신경써야할 것들이 상당히 많은데요.</p>
  3683.  
  3684.  
  3685.  
  3686. <p style="font-size:16px">이번에는 그 중에서 모니터링에 초점을 맞춰, 리멤버는 서비스 모니터링을 어떻게 하고 있는지에 대해서 소개하려고 합니다.</p>
  3687.  
  3688.  
  3689.  
  3690. <p></p>
  3691.  
  3692.  
  3693.  
  3694. <h4>리멤버에서 사용하는 모니터링 도구 : AWS CloudWatch 와 New Relic</h4>
  3695.  
  3696.  
  3697.  
  3698. <p>저희 리멤버 서비스는 대부분 AWS 위에 구축해놓은 infrastructure 를 기반으로 운영되고 있습니다.</p>
  3699.  
  3700.  
  3701.  
  3702. <p>따라서 AWS CloudWatch 를 적극적으로 활용하여 적절한 지표 및 Alarm/Alert 를 설정하는 것이 중요합니다.</p>
  3703.  
  3704.  
  3705.  
  3706. <p>또한, AWS CloudWatch 만으로는 서비스에서 발생하는 모든 이벤트들에 대해 파악하기가 쉽지 않기 때문에, APM 등을 도입하여 모니터링하는 것도 중요합니다.</p>
  3707.  
  3708.  
  3709.  
  3710. <p>이를 위해 리멤버에서는 모니터링 플랫폼으로써 New Relic 을 오래전부터 사용해오고 있었습니다.</p>
  3711.  
  3712.  
  3713.  
  3714. <figure class="wp-block-embed aligncenter is-type-wp-embed is-provider-drama-amp-company wp-block-embed-drama-amp-company"><div class="wp-block-embed__wrapper">
  3715. <blockquote class="wp-embedded-content" data-secret="OFgYErXEBz"><a href="https://blog.dramancompany.com/2015/12/%ec%95%88%ec%a0%95%ec%a0%81%ec%9d%b8-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ec%9d%84-%ec%9c%84%ed%95%9c-%ec%84%9c%eb%b2%84-%eb%aa%a8%eb%8b%88%ed%84%b0%eb%a7%81-1/">안정적인 서비스 운영을 위한 서버 모니터링 #1</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" title="&#8220;안정적인 서비스 운영을 위한 서버 모니터링 #1&#8221; &#8212; DRAMA&amp;COMPANY" src="https://blog.dramancompany.com/2015/12/%ec%95%88%ec%a0%95%ec%a0%81%ec%9d%b8-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ec%9d%84-%ec%9c%84%ed%95%9c-%ec%84%9c%eb%b2%84-%eb%aa%a8%eb%8b%88%ed%84%b0%eb%a7%81-1/embed/#?secret=ApEKP75wZS#?secret=OFgYErXEBz" data-secret="OFgYErXEBz" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
  3716. </div></figure>
  3717.  
  3718.  
  3719.  
  3720. <h4>리멤버에서 모니터링하는 것들</h4>
  3721.  
  3722.  
  3723.  
  3724. <h5>Application Performance</h5>
  3725.  
  3726.  
  3727.  
  3728. <p>New Relic 을 이용하여 서버의 처리량(throughput), 평균 응답 시간, 오류 발생율(Error rate), Slow transactions 가 있는지, Host 의 CPU/Memory 사용율 등을 주로 확인합니다. Error rate 가 0% 초과라면 어떤 Error 가 발생했는지, 해당 Error 가 발생했던 thread 의 stack trace 도 확인하며, 관련 logs 도 조회하면서 어떤 문제가 있는지 진단합니다.</p>
  3729.  
  3730.  
  3731.  
  3732. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?ssl=1"><img data-attachment-id="2975" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-8/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?fit=1200%2C882&amp;ssl=1" data-orig-size="1200,882" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="apm-summary" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?fit=300%2C221&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?fit=1024%2C753&amp;ssl=1" loading="lazy" width="1024" height="753" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?resize=1024%2C753&#038;ssl=1" alt="" class="wp-image-2975" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?resize=1024%2C753&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?resize=300%2C221&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?resize=768%2C564&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?resize=750%2C551&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?resize=1140%2C838&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image.png?w=1200&amp;ssl=1 1200w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>Application Performance Monitoring</figcaption></figure></div>
  3733.  
  3734.  
  3735.  
  3736. <p></p>
  3737.  
  3738.  
  3739.  
  3740. <h5>Infrastructure Metrics</h5>
  3741.  
  3742.  
  3743.  
  3744. <p>서비스를 위한 프로세스가 실행중인 서버(EC2, ECS 등)는 하나의 애플리케이션 서버만을 실행하긴 하지만, 애플리케이션 서버 프로세스가 아닌 다른 요인으로 서버에 문제가 발생할 수도 있습니다. 애플리케이션의 트래픽은 낮은데 IO가 높을 수도 있고, Disk Usage 가 100% 가 돼 서비스 불능 상태에 이를 수 있는 등 APM 뿐 아니라 Infrastructure 관점에서의 여러 metrics 도 봐야합니다. 리멤버에서는 이 또한 주로 New Relic 을 활용하여 모니터링하고 있습니다.</p>
  3745.  
  3746.  
  3747.  
  3748. <p>여기서 Load average, CPU 사용율을 중심으로 어떤 서버에 부하가 쏠리는지, 어떤 프로세스가 문제가 되고 있는지 등을 파악할 수 있습니다.</p>
  3749.  
  3750.  
  3751.  
  3752. <p>여러 지표를 확인 후 문제가 발견됐다면 조치를 취하고 앞으로는 동일한 문제가 발생하지 않도록 하기 위해 취한 조치를 자동화하고 있습니다. 개발자들이 알게 모르게 시간을 많이 쏟고 있는 반복 작업들(<a href="https://sre.google/sre-book/eliminating-toil/" target="_blank" rel="noreferrer noopener">Toil</a>) 들을 자동화하기 위해 꼭 필요한 지표들입니다.</p>
  3753.  
  3754.  
  3755.  
  3756. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?ssl=1"><img data-attachment-id="2976" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-1-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?fit=1500%2C1144&amp;ssl=1" data-orig-size="1500,1144" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?fit=300%2C229&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?fit=1024%2C781&amp;ssl=1" loading="lazy" width="1024" height="781" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?resize=1024%2C781&#038;ssl=1" alt="" class="wp-image-2976" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?resize=1024%2C781&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?resize=300%2C229&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?resize=768%2C586&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?resize=750%2C572&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?resize=1140%2C869&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-1.png?w=1500&amp;ssl=1 1500w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>Infrastructure Metrics &#8211; System</figcaption></figure></div>
  3757.  
  3758.  
  3759.  
  3760. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?ssl=1"><img data-attachment-id="2977" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-2-3/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?fit=1500%2C1102&amp;ssl=1" data-orig-size="1500,1102" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?fit=300%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?fit=1024%2C752&amp;ssl=1" loading="lazy" width="1024" height="752" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?resize=1024%2C752&#038;ssl=1" alt="" class="wp-image-2977" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?resize=1024%2C752&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?resize=300%2C220&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?resize=768%2C564&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?resize=750%2C551&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?resize=1140%2C838&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-2.png?w=1500&amp;ssl=1 1500w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>Infrastructure Metrics &#8211; Storage</figcaption></figure></div>
  3761.  
  3762.  
  3763.  
  3764. <p></p>
  3765.  
  3766.  
  3767.  
  3768. <h5>SLI/SLO</h5>
  3769.  
  3770.  
  3771.  
  3772. <p>서비스에 문제가 있는지 없는지 현황을 한 눈에 파악하기위해서 적절한 SLI 와 SLO 를 설정하고, 이를 모니터링하는 것이 가장 기본적인 방법입니다.</p>
  3773.  
  3774.  
  3775.  
  3776. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?ssl=1"><img data-attachment-id="3006" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-5-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?fit=3360%2C794&amp;ssl=1" data-orig-size="3360,794" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-5" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?fit=300%2C71&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?fit=1024%2C242&amp;ssl=1" loading="lazy" width="1024" height="242" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=1024%2C242&#038;ssl=1" alt="" class="wp-image-3006" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=1024%2C242&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=300%2C71&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=768%2C181&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=1536%2C363&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=2048%2C484&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=750%2C177&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?resize=1140%2C269&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-5.png?w=3000&amp;ssl=1 3000w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>Service Levels</figcaption></figure></div>
  3777.  
  3778.  
  3779.  
  3780. <p></p>
  3781.  
  3782.  
  3783.  
  3784. <p>리멤버는 아직 별도의 SRE 또는 DevOps 포지션이 없는 형태의 조직 구조이기 때문에, 이 SLI/SLO 를 설정하고 모니터링하기 시작한 건 얼마 되지 않았습니다.</p>
  3785.  
  3786.  
  3787.  
  3788. <p>이 글을 쓰는 시점 기준 아직 SLI/SLO 설정을 하지 못한 서비스들도 있습니다. 점진적으로 하나씩 하나씩 저희 서비스의 상태를 가장 빠르게 확인할 수 있도록 필요한 SLI/SLO 를 추가하고 있습니다. 혹시, 독자분들 중에서 이에 대해 관심을 가지신 분이 계시다면, 리멤버에 합류하셔서 함께 만들어 나가보는 것은 어떨까요? <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f923.png" alt="🤣" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  3789.  
  3790.  
  3791.  
  3792. <p>SLI/SLO 설정을 하고 이를 볼 수 있는 페이지를 만드는 것도 자체적으로 할 수도 있고, 3rd party saas 등을 이용할 수도 있는데, 저희는 이미 사용하고 있는 New Relic 에서 제공해주고 있는 Service Levels 기능을 통해 최소한의 리소스 투입으로 만들어가고 있습니다.</p>
  3793.  
  3794.  
  3795.  
  3796. <p></p>
  3797.  
  3798.  
  3799.  
  3800. <h5>특정 서비스의 health 를 나타내는 지표</h5>
  3801.  
  3802.  
  3803.  
  3804. <p>애플리케이션의 도메인 특성상 관리해야하는 지표가 있을 수 있습니다. 예를 들어, 리멤버에 있는 명함을 구글 연락처로 동기화하는 기능을 제공하고 있습니다. 사용자의 행태에 따라 동기화해야할 명함 수가 급격하게 늘어나는 때가 종종 생기는데, 그런 경우 개발자들이 인지하고 적절한 조치를 취하거나 개선할 수 있도록 CloudWatch 에 custom metric 을 전송하고, Alarm 을 만들어 관찰하고 있습니다.</p>
  3805.  
  3806.  
  3807.  
  3808. <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?ssl=1"><img data-attachment-id="3004" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-3-3/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?fit=1388%2C778&amp;ssl=1" data-orig-size="1388,778" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-3" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?fit=300%2C168&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?fit=1024%2C574&amp;ssl=1" loading="lazy" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?resize=857%2C480&#038;ssl=1" alt="" class="wp-image-3004" width="857" height="480" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?resize=1024%2C574&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?resize=768%2C430&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?resize=750%2C420&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?resize=1140%2C639&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-3.png?w=1388&amp;ssl=1 1388w" sizes="(max-width: 857px) 100vw, 857px" data-recalc-dims="1" /></a><figcaption>CloudWatch 의 custom metric 및 이에 대한 alarm</figcaption></figure></div>
  3809.  
  3810.  
  3811.  
  3812. <p>물론, 이렇게 설정해놓은 Alarm 이 자주 발생하거나 어떻게 조치를 취해야하는지에 대해 명확하게 알고 있다면, 아래의 스크린샷과 같이 자동화하여 더 이상 중요하지 않은 이유로 Alarm 이 오지 않도록 개선하는 것도 중요합니다.</p>
  3813.  
  3814.  
  3815.  
  3816. <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?ssl=1"><img data-attachment-id="3005" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-4-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?fit=1544%2C1250&amp;ssl=1" data-orig-size="1544,1250" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-4" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?fit=300%2C243&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?fit=1024%2C829&amp;ssl=1" loading="lazy" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=858%2C694&#038;ssl=1" alt="" class="wp-image-3005" width="858" height="694" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=1024%2C829&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=300%2C243&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=768%2C622&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=1536%2C1244&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=750%2C607&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?resize=1140%2C923&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-4.png?w=1544&amp;ssl=1 1544w" sizes="(max-width: 858px) 100vw, 858px" data-recalc-dims="1" /></a><figcaption>Alarm 을 확인 하고 더 이상 같은 Alarm 이 오지 않도록 개선 및 자동화 예시</figcaption></figure></div>
  3817.  
  3818.  
  3819.  
  3820. <p></p>
  3821.  
  3822.  
  3823.  
  3824. <p>이러한 것들 외에도 Distributed traces, Service Map 등 다양한 관점에서 저희 서비스가 안정적으로 운영이 되고 있는지, 새로운 병목 구간이 생기지는 않았는지 등을 끊임없이 모니터링하고 있습니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  3825.  
  3826.  
  3827.  
  3828. <p></p>
  3829.  
  3830.  
  3831.  
  3832. <p>다음으로는 이렇게 갖춰놓은 모니터링 시스템을 활용한 예시 몇가지를 소개드리겠습니다.</p>
  3833.  
  3834.  
  3835.  
  3836. <p></p>
  3837.  
  3838.  
  3839.  
  3840. <h4 class="has-medium-font-size">모니터링 시스템 활용 사례</h4>
  3841.  
  3842.  
  3843.  
  3844. <h5>리멤버에서 이상 징후를 발견하는 방법</h5>
  3845.  
  3846.  
  3847.  
  3848. <p>주로 문제가 생겼을 때 Slack 의 특정 채널(장애 알림 전용 채널)에 메시지가 게시되는 것으로부터 가장 빠르게 인지를 합니다. Slack 에 장애가 발생하면 리멤버 서비스에 발생하는 장애를 인지하기 어려워지기 때문에 극소수이긴 하지만 일부 구성원들, 일부 지표에 한해서는 이메일로도 받도록 돼있는 부분도 있습니다.</p>
  3849.  
  3850.  
  3851.  
  3852. <p>Slack 으로 인지하게 되는 것과 별개로 위 문단에 적어놓은 것과 같이 모니터링을 하다가 발견하는 경우도 있습니다. 모니터링 중 특별히 튀는 지표가 눈에 띄면 Alert 와 무관하게 원인 파악을 하며 문제인지 아닌지 판단을 하고 문제 상황이라면 triage(심각도 정도에 따른 우선 순위 분류)부터 시작하여 Troubleshooting 을 시작하기도 합니다.</p>
  3853.  
  3854.  
  3855.  
  3856. <ul><li>New Relic 에서 제공하는 terraform 모듈을 이용하여 각 애플리케이션 마다 Slack 으로 알람 메시지가 오도록 하는 Alert 를 생성/관리하고 있습니다.<ul><li>New Relic 은 글로벌 서비스인만큼 사용자도 많고, 이를 활용한 오픈 소스도 많은데요. 저도 <a href="https://developer.newrelic.com/automate-workflows/get-started-terraform/">New Relic 에서 제공해주는 매뉴얼</a>을 참고하는 것은 물론, github 에서 오픈 소스를 검색해 참고하여 저희만의 terraform 코드를 만들어 IaC 로 New Relic Alert 를 관리하고 있습니다.</li></ul></li></ul>
  3857.  
  3858.  
  3859.  
  3860. <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?ssl=1"><img data-attachment-id="3036" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-9/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?fit=1500%2C835&amp;ssl=1" data-orig-size="1500,835" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-9" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?fit=300%2C167&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?fit=1024%2C570&amp;ssl=1" loading="lazy" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?resize=667%2C371&#038;ssl=1" alt="" class="wp-image-3036" width="667" height="371" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?resize=1024%2C570&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?resize=300%2C167&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?resize=768%2C428&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?resize=750%2C418&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?resize=1140%2C635&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-9.png?w=1500&amp;ssl=1 1500w" sizes="(max-width: 667px) 100vw, 667px" data-recalc-dims="1" /></a><figcaption>실제로 리멤버에서 사용하고 있는 newrelic terraform module 코드 조각</figcaption></figure></div>
  3861.  
  3862.  
  3863.  
  3864. <ul><li>이렇게 설정해놓은 New Relic Alert 의 조건이 발동되면 아래와 같이 Slack 에서 어떤 문제가 있는지 확인할 수 있습니다.<ul><li>Slack 으로 Alert 가 오는 것을 확인하면 즉시 확인하여 원인이 무엇인지 파악하고 해결을 하면서 그 과정을 thread 로 기록하고 있습니다. thread 로 기록하는 이유는 재발 방지를 도모하고, 이런 문제가 있었다는 것을 다른 분들도 다 확인하실 수 있도록 하고 있습니다. 다른 사람들이 thread 로 기록해놓은 해결 과정을 따라가보면 새로운 인사이트를 얻게 되는 경우도 많답니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f602.png" alt="😂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li></ul></li></ul>
  3865.  
  3866.  
  3867.  
  3868. <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?ssl=1"><img data-attachment-id="3038" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-10/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?fit=951%2C1200&amp;ssl=1" data-orig-size="951,1200" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-10" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?fit=238%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?fit=812%2C1024&amp;ssl=1" loading="lazy" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?resize=429%2C541&#038;ssl=1" alt="" class="wp-image-3038" width="429" height="541" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?resize=812%2C1024&amp;ssl=1 812w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?resize=238%2C300&amp;ssl=1 238w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?resize=768%2C969&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?resize=750%2C946&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-10.png?w=951&amp;ssl=1 951w" sizes="(max-width: 429px) 100vw, 429px" data-recalc-dims="1" /></a><figcaption>New Relic Alert 가 Slack 으로 게시된 모습</figcaption></figure></div>
  3869.  
  3870.  
  3871.  
  3872. <p></p>
  3873.  
  3874.  
  3875.  
  3876. <ul><li>또한 AWS CloudWatch + SNS 를 이용하여 Slack 으로 알람 메시지가 오도록 연동하여 사용하고 있는 것도 많이 있습니다.<ul><li>이 글을 작성하고 있는 시간 기준으로 AWS CloudWatch 에는 411개의 Alarm 이 있습니다. 이 중에는 더 이상 무의미하여 삭제해도 되는데 삭제하지 못하고 있는 Alarm 도 다수 포함이 돼있습니다.</li><li>Alarm 이 슬랙으로 전송되면 아래와 같은 형태로 확인할 수 있습니다.</li></ul></li></ul>
  3877.  
  3878.  
  3879.  
  3880. <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?ssl=1"><img data-attachment-id="3039" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-11/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?fit=1258%2C744&amp;ssl=1" data-orig-size="1258,744" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-11" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?fit=300%2C177&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?fit=1024%2C606&amp;ssl=1" loading="lazy" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?resize=664%2C393&#038;ssl=1" alt="" class="wp-image-3039" width="664" height="393" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?resize=1024%2C606&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?resize=300%2C177&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?resize=768%2C454&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?resize=750%2C444&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?resize=1140%2C674&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-11.png?w=1258&amp;ssl=1 1258w" sizes="(max-width: 664px) 100vw, 664px" data-recalc-dims="1" /></a><figcaption>DLQ(Dead Letter Queue) 로 설정해놓은 특정 SQS queue 에 메시지가 전송됐을 때 Alarm 이 Slack 으로 게시된 모습</figcaption></figure></div>
  3881.  
  3882.  
  3883.  
  3884. <h4>모니터링 시스템 활용 troubleshooting 사례</h4>
  3885.  
  3886.  
  3887.  
  3888. <p>여기서 말하는 troubleshooting 이라 함은 크게 특정 사용자에게 어떤 문제가 생겨 문의를 주신 경우에 대응하여 처리하는 것과 서비스의 지표에 이상징후가 생겨 대응하는 것으로 나눌 수 있습니다.</p>
  3889.  
  3890.  
  3891.  
  3892. <p>어떤 문제가 생겨 유저께서 문의를 하신 경우에는 가장 먼저 Logs 에서 해당 유저가 요청한 API 목록을 가장 먼저 확인하여, 어떤 일들이 있었는지 파악하고 해결해드리고 있습니다.</p>
  3893.  
  3894.  
  3895.  
  3896. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?ssl=1"><img data-attachment-id="3007" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-6-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?fit=2036%2C1116&amp;ssl=1" data-orig-size="2036,1116" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-6" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?fit=300%2C164&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?fit=1024%2C561&amp;ssl=1" loading="lazy" width="1024" height="561" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=1024%2C561&#038;ssl=1" alt="" class="wp-image-3007" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=1024%2C561&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=300%2C164&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=768%2C421&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=1536%2C842&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=750%2C411&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?resize=1140%2C625&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-6.png?w=2036&amp;ssl=1 2036w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>New Relic 에서 본 Logs</figcaption></figure></div>
  3897.  
  3898.  
  3899.  
  3900. <p></p>
  3901.  
  3902.  
  3903.  
  3904. <p>서비스의 지표에 이상징후가 생겨 대응할 때에는 그 종류에 따라 달라지겠지만, CloudWatch, NewRelic 등 수단과 방법을 가리지 않고 원인 파악을 위해 적절한 지표와 로그를 찾고 Troubleshooting 을 하고 있습니다.</p>
  3905.  
  3906.  
  3907.  
  3908. <p>아래는 특정 서비스에서 Errors 가 동시 다발적으로 발생하여, 모니터링 시스템을 이용하여 원인을 파악하고 개선하기 위해 커뮤니케이션 했던 흔적입니다.</p>
  3909.  
  3910.  
  3911.  
  3912. <div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?ssl=1"><img data-attachment-id="3008" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-7-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?fit=1774%2C1612&amp;ssl=1" data-orig-size="1774,1612" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-7" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?fit=300%2C273&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?fit=1024%2C930&amp;ssl=1" loading="lazy" width="1024" height="930" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=1024%2C930&#038;ssl=1" alt="" class="wp-image-3008" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=1024%2C930&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=300%2C273&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=768%2C698&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=1536%2C1396&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=750%2C682&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?resize=1140%2C1036&amp;ssl=1 1140w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-7.png?w=1774&amp;ssl=1 1774w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1" /></a><figcaption>Error rate 지표를 확인하고 개선하고 있는 예시</figcaption></figure></div>
  3913.  
  3914.  
  3915.  
  3916. <p></p>
  3917.  
  3918.  
  3919.  
  3920. <p></p>
  3921.  
  3922.  
  3923.  
  3924. <h3>부록 &#8211; 리멤버에서는 왜 이렇게 모니터링을 하고 있을까</h3>
  3925.  
  3926.  
  3927.  
  3928. <p>위 본문에서 소개드린 것 외에도 모니터링은 곳곳에서 다양한 도구와 방법을 통해서 하고 있습니다. 예를 들어, Monyog 을 이용하여 데이터베이스를 모니터링하고 있기도 하고요. </p>
  3929.  
  3930.  
  3931.  
  3932. <p>결국 모니터링 하는 이유는 사용자에게 안정적인 서비스를 제공하기 위함이기 때문에 저희가 현재 모니터링을 하고 있지 않은 영역을 찾아서 모니터링 범위에 포함시키고 지속적으로 개선하기 위해 노력하고 있습니다. 특정 모니터링 시스템/플랫폼에 종속되거나 스스로 locked-in 될 필요는 없지만, 모니터링을 잘 하려면(=안정적인 서비스를 제공하려면) 사내에서 사용하고 있는 모니터링 시스템/플랫폼에 대해 익숙해지고 잘 사용할 줄 아는 것도 중요합니다.</p>
  3933.  
  3934.  
  3935.  
  3936. <p>그렇기 때문에 우리 회사에서의 모니터링 시스템은 왜 이런 모습이 됐을까를 이해하는 것도 모니터링 시스템/플랫폼에 익숙해지는 데 큰 도움이 될 것이란 생각이 들었기 때문에 부록으로 &#8220;리멤버에서는 왜 이렇게 모니터링을 하고 있을까&#8221;라는 질문에 대해 일부 답변이 될 만한 내용들을 정리해보려 합니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  3937.  
  3938.  
  3939.  
  3940. <h4>입사 당시의 상황</h4>
  3941.  
  3942.  
  3943.  
  3944. <p style="font-size:16px">2019년 12월, 제가 리멤버에 합류할 때 당시를 떠올려보면 그 때도 안정적인 서비스를 위해 모니터링을 잘 하고 있었습니다. 하지만 직접 개발, 운영하면서 느꼈던 부족한점, 아쉬운 점들이 있기도 했습니다.</p>
  3945.  
  3946.  
  3947.  
  3948. <h6 style="font-size:16px">다원화된 로그(logs)와 지표(metrics) 데이터</h6>
  3949.  
  3950.  
  3951.  
  3952. <ul style="font-size:16px"><li>ElasticSearch 로 전송하고 ElasticSearch 에서 로그를 저장/인덱싱을 하면 Kibana 에서 로그를 조회하는 일반적인 구성이었습니다. 이 시스템 자체는 문제가 없었지만, 일부 서비스는 ELK 연동이 안 돼있어서 AWS 의 CloudWatch 에서 로그를 보거나 EC2 에 직접 SSH 접속을 해서 봐야 하는 경우도 있었습니다. 또한 직접 EC2 에 구성하고 운영하고 있던 ElasticSearch 는 가끔씩이지만 인덱싱 문제를 일으켰고, 그 때마다 일부 로그 유실이 발생했고 자주 발생하는 일이 아니었기 때문에 노하우가 없어 문제가 생기면 복구를 위한 시간이 상당히 많이 소요됐습니다.</li><li>로그는 ELK 에서 보면 되는데, 로그와 연관된 서버의 상태(CPU, memory 사용율 등)는 AWS console 에서 보거나 당시에도 연동돼 있던 NewRelic 에서 확인해야만 했습니다. 이렇게 이원화가 돼있다 보니 개발자가 무언가를 파악해야할 때마다 확인해봐야 하는 데이터들이 흩어져있어 신경쓰고 있어야 하는 컨텍스트가 많아져 비효율이 있었습니다. 특히 새로 합류하는 개발자 입장에서는 어떤 것은 여기서 보고, 어떤 것은 저기서 봐야하는 암묵지처럼 돼버린 것을 이해하고 활용하기까지는 시간이 적지 않게 걸렸습니다.</li></ul>
  3953.  
  3954.  
  3955.  
  3956. <h5 style="font-size:16px">이상 징후에 대한 alert/alarm 이 구성돼있지만, 뭘 해야할 지 판단하기 어려움</h5>
  3957.  
  3958.  
  3959.  
  3960. <ul style="font-size:16px"><li>오래전 AWS Cloudwatch 및 NewRelic 에서 설정해놓은 Alert 가 있어서 서비스에 문제가 생기거나 생길 것으로 예상될 때마다 슬랙으로 Alarm 이 오긴 왔지만, 해당 Alarm 을 본 개발자가 어떤 문제가 있는 것인지, 어떤 조치를 해야하는지에 대한 파악이 쉽지 않았습니다. 문제가 생기면 그때 그때 특별한 컨벤션, 규칙, 기준없이 alert 를 만들어왔던 것들이 꽤 많았었고, alert 가 있었기 때문에 문제가 발생했다는 사실은 쉽게 인지할 수 있었는데, 그 alert 를 보고 원인 분석을 위해서 어떻게 시작해야하는 지에 대해서는 회사에서 일정 기간 이상 근무를 한 개발자가 아닌 이상 파악하기가 쉽지 않았습니다.</li></ul>
  3961.  
  3962.  
  3963.  
  3964. <h5 style="font-size:16px">service map 파악의 어려움</h5>
  3965.  
  3966.  
  3967.  
  3968. <ul style="font-size:16px"><li>기존에 monolithic 한 하나의 서비스에서 벗어나, 여러 신규 서비스들은 소스코드부터 인프라까지 별도로 구축하고 있었습니다. 이 때, 서비스들 간의 통신이 어떻게 되고 있는지 등을 파악하려면 지속적으로 업데이트되는 Service Map 을 쉽게 볼 수 있는 것이 중요한데, 이때까지는 사람이 수작업으로 위키(컨플루언스) 문서로 관리하고 있었습니다. 결국 사람이 하는 문서 관리이다 보니, 현행화가 잘 이뤄지지 않게 되거나 문서의 존재조차 모르고 우리 서비스들의 Service Map 을 그려달라고 하는 개발자분들이 생길 수 밖에 없었습니다.</li></ul>
  3969.  
  3970.  
  3971.  
  3972. <h5 style="font-size:16px">웹, 모바일 애플리케이션에서 일어나는 이벤트(에러, 버그 등)들에 대한 파악의 어려움</h5>
  3973.  
  3974.  
  3975.  
  3976. <ul><li>이건 이 글을 쓰고 있는 현재 시점 기준으로도 아직 잘 하고 있지 못한 부분입니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f62d.png" alt="😭" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f62d.png" alt="😭" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li></ul>
  3977.  
  3978.  
  3979.  
  3980. <p></p>
  3981.  
  3982.  
  3983.  
  3984. <h4>문제점 인식</h4>
  3985.  
  3986.  
  3987.  
  3988. <p style="font-size:16px">사내에 개발자가 늘어남에 따라 서버의 상태나 애플리케이션의 지표, 로그를 한 군데에서 보는 것이 더욱 중요해지고 있었습니다. 새로 합류하시는 개발자에게 모니터링 현황 및 배경에 대해 설명해드리는 것조차 각오하고 해야하는 큰 일이 되고 있었습니다. 문서로 커뮤니케이션 하는 것의 한계가 느껴지기 시작하기도 했습니다.</p>
  3989.  
  3990.  
  3991.  
  3992. <p style="font-size:16px">&#8220;모든 로그를 하나의 시스템으로 모아서 보자. 로그와 여러 지표도 하나의 시스템에서 확인할 수 있게 하자.&#8221; 를 달성하기 위해 이미 많은 비용을 지불하고 있던 NewRelic 을 잘 활용해보자고 의사 결정이 2021년 6월쯤 이뤄졌습니다.</p>
  3993.  
  3994.  
  3995.  
  3996. <p style="font-size:16px"></p>
  3997.  
  3998.  
  3999.  
  4000. <h4>New Relic 을 사용하는 이유</h4>
  4001.  
  4002.  
  4003.  
  4004. <h5>비용</h5>
  4005.  
  4006.  
  4007.  
  4008. <p>기존에도 비용을 지불하며 New Relic 의 APM 기능을 연동하여 사용하고 있었습니다.</p>
  4009.  
  4010.  
  4011.  
  4012. <p>기존에 로그를 쌓고 조회하기 위해 자체적으로 ELK 를 운영하던 것에도 적지 않은 비용이 발생하고 있었습니다. 데이터의 다원화 등으로 인해 발생하는 눈에 보이지 않는 생산성 저하 등의 비용도 무시할 수 없었습니다. New Relic 이 아니더라도 기존에 ELK 에 통합하든, 새로운 모니터링 시스템을 자체적으로 구축하든 큰 비용이 필요했습니다. 이 중에서 New Relic 을 선택하는 것이 그 당시 가장 합리적인 것이었습니다.</p>
  4013.  
  4014.  
  4015.  
  4016. <p><a href="https://blog.dramancompany.com/2015/12/%EC%95%88%EC%A0%95%EC%A0%81%EC%9D%B8-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%9A%B4%EC%98%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%84%9C%EB%B2%84-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-2/" target="_blank" rel="noreferrer noopener">과거에 ELK 로 선택한 것과 관련한 블로그 포스트</a></p>
  4017.  
  4018.  
  4019.  
  4020. <h5>생산성</h5>
  4021.  
  4022.  
  4023.  
  4024. <p>애플리케이션과 연결된 Database layer 까지 포함한 여러 지표를 확인할 수 있습니다. 이를 통해 trace 의 여러 spans 중 어디가 병목인지 쉽게 분류할 수 있습니다. 또한, 별도의 시스템을 구축하지 않아도 APM 기능 안에서 N+1 쿼리 발생 여부, slow query 발생한 trace 등을 쉽게 파악할 수 있습니다. 이것들이 쉽게 파악이 되며, 계속 눈에 띈다면 개발자로서 조치를 취하지 않을 수 없게 됩니다. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>
  4025.  
  4026.  
  4027.  
  4028. <p>그래프, 차트 등 데이터 시각화가 잘 돼있어, 개발자가 현황을 파악하거나 문제의 원인 분석 등을 빠르게 할 수 있습니다.</p>
  4029.  
  4030.  
  4031.  
  4032. <h5>분산 트레이싱 환경</h5>
  4033.  
  4034.  
  4035.  
  4036. <p>Prometheus + Grafana, Sentry 같은 오픈소스 제품이나 New Relic, DataDog, Dynatrace 등 3rd party SaaS 를 사용하면 분산 트랜잭션 환경에서 유저 관점에서 하나의 trace 와 관련한 logs, traces, error 를 seamless 하게 확인할 수 있습니다.</p>
  4037.  
  4038.  
  4039.  
  4040. <p>여러 부분, 여러 관점에서 꼭 New Relic 이 아니더라도 같은 수준 혹은 더 높은 수준의 요구 사항을 만족시켜주는 좋은 제품들도 많이 있는 것으로 알고 있습니다.</p>
  4041.  
  4042.  
  4043.  
  4044. <p>하지만 현재 New Relic 을 사용하고 있는 리멤버의 개발자들과 앞으로 합류해주실 분들께 지금 New Relic 을 사용하는 이유에 대해 설명을 드리고 공감을 얻는 것이 중요하기 때문에 제가 알고 있는 배경에 대해 정리해봤습니다.</p>
  4045.  
  4046.  
  4047.  
  4048. <p></p>
  4049.  
  4050.  
  4051.  
  4052. <p>배경과 더불어 실제로 사용해보면서 개인적으로 느꼈던 장점과 단점에 대해서도 정리를 해보면, New Relic 또는 기타 제품들을 고민하고 있는 단계에 있는 분들께 도움이 될 것 같아서 아래에 간략하게 정리해보려고 합니다. 다시 한 번 말씀드리지만, 이 글을 쓰고 있는 제 개인적인 느낀점일 뿐인 점을 감안하고 봐주시길 부탁 드립니다.  <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  4053.  
  4054.  
  4055.  
  4056. <h4 style="font-size:16px">New Relic 의 단점</h4>
  4057.  
  4058.  
  4059.  
  4060. <ul style="font-size:16px"><li>애플리케이션에서 의존성으로 설치하는 APM agent 와는 별개로 infrastructure agent 를 설치해야했으며(소스 코드로 관리하기가 다소 번거로운 점), EC2 로 운용하는 경우 agent 버전 업데이트, 설정 변경 등 필요하면 AMI 를 새로 생성하는 작업 등 관리 포인트가 증가했습니다.<ul><li>애플리케이션 서버의 로그를 New Relic 으로 전송하기 위해 별도의 Log forwarder 도 설정을 해줘야만 했던 점도 불편한 점이었습니다.<ul><li>2022년 5월 이후 애플리케이션 서버 로그는 최신 버전의 APM agent 를 의존성으로 추가하는 것만으로 자동으로 수집이 되게 업데이트 된 것을 확인하긴 했습니다.</li></ul></li></ul></li><li>서버에 설치된 보안 프로그램(trend micro 사의 deep security) 또는 aws-ssm-agent 프로세스와의 충돌 이슈로 인해 트래픽이 적은데도 CPU 100% 이슈가 생기는 EC2 들이 가끔 발생했습니다. deep security 의 특정 rule 때문에 발생하는 것인지, New Relic 의 infrastructure agent 작동 방식 때문에 발생하는 것인지 정확한 진단이 어려웠습니다. 하지만 이런 일이 생길 때마다 적극적으로 지원해주시기 때문에 큰 걱정은 하지 않지만, 정확한 원인 진단은 잘 되지 않았기 때문에 아쉬움이 생기긴 했습니다.</li><li>NRQL(New Relic Query Language) 을 학습해야 활용도가 매우 커지는데, 학습 곡선의 초반부 기울기가 낮습니다.<ul><li>즉, NRQL 을 일정 수준 이상 학습하기 전까지는 잘 활용하기가 어렵습니다.</li><li>학습 곡선은 가로축이 시간/노력/누적 경험수이고, 세로축이 달성도, 성취, 습득 정도인 곡선입니다. 기울기가 낮다는 의미가 초반에는 들이는 노력에 비해 일정 수준 이상 학습(성취)되기 까지 시간이 오래 걸린다는 의미입니다.</li></ul></li></ul>
  4061.  
  4062.  
  4063.  
  4064. <p></p>
  4065.  
  4066.  
  4067.  
  4068. <h5 style="font-size:16px">New Relic 의 장점</h5>
  4069.  
  4070.  
  4071.  
  4072. <p style="font-size:16px">여기 나열한 것들은 New Relic 만의 장점은 아닐 것입니다. 그렇지만, 연동부터 운영까지 해보며 장점으로 느껴진 부분들을 정리해보았습니다.</p>
  4073.  
  4074.  
  4075.  
  4076. <ul style="font-size:16px"><li>애플리케이션의 의존성으로 APM agent 를 추가하기만 하면 각종 지표를 손쉽게 확인할 수 있습니다.</li><li>New Relic 의 여러 리소스들(eg. Alert)을 생성/수정/관리를 API, terraform 모듈로 제공해주고 있어 한 번 구성해놓으면 편리합니다.</li><li>원하는 데이터를 보기 위한 dashboard 를 자유자재로 만들 수 있습니다.</li><li>Service Map 을 쉽게 확인할 수 있습니다.</li><li>SRE 를 위한 SLI/SLO 정의가 쉽고 한 눈에 보기 쉬운 페이지를 제공합니다.<ul><li>이 기능은 최근에 업데이트 된 것으로 알고 있는데, 하나씩 추가해보고 있습니다. SLI/SLO 설정 및 대시보드를 만들기 위해 자체적으로 개발을 해야하나 고민을 하던 찰나에 이 기능을 발견해서 써보고 있는데, 아직까지는 만족스럽습니다.</li></ul></li><li>제품 업데이트가 빠르고 많습니다.<ul><li>실제로 작년에 처음 사용을 본격적으로 시작할 때를 떠올려보면 지금은 정말 많은 기능 추가/개선이 생겼음을 느낍니다.</li></ul></li><li>브라우저 및 모바일 애플리케이션에 대해서도 모니터링이 가능합니다.<ul><li>하지만 리멤버에서는 아직 이 장점을 잘 활용하고 있지는 않습니다.</li></ul></li><li>Synthetics 를 활용하여 실제 사용자가 사용하는 시나리오대로 테스트를 구성하고 원할 때 테스트가 실행되도록 하여 사용자가 실제 문제를 겪기 전에 사전에 개발자들이 문제를 파악할 수 있습니다. 이 또한 아직 리멤버에서는 잘 활용하고 있지 않습니다.</li></ul>
  4077.  
  4078.  
  4079.  
  4080. <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?ssl=1"><img data-attachment-id="3011" data-permalink="https://blog.dramancompany.com/2022/06/how-remember-monitors/image-8-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?fit=2162%2C1302&amp;ssl=1" data-orig-size="2162,1302" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-8" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?fit=300%2C181&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?fit=1024%2C617&amp;ssl=1" loading="lazy" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=678%2C409&#038;ssl=1" alt="" class="wp-image-3011" width="678" height="409" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=1024%2C617&amp;ssl=1 1024w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=300%2C181&amp;ssl=1 300w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=768%2C463&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=1536%2C925&amp;ssl=1 1536w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=2048%2C1233&amp;ssl=1 2048w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=750%2C452&amp;ssl=1 750w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2022/06/image-8.png?resize=1140%2C687&amp;ssl=1 1140w" sizes="(max-width: 678px) 100vw, 678px" data-recalc-dims="1" /></a><figcaption>New Relic 에서 자동으로 만들어 준 Service Map 중 하나</figcaption></figure></div>
  4081.  
  4082.  
  4083.  
  4084. <p></p>
  4085.  
  4086.  
  4087.  
  4088. <p>이것으로 리멤버에서는 어떻게 모니터링을 하고 있는지에 대해 소개드리는 글을 마치겠습니다.</p>
  4089.  
  4090.  
  4091.  
  4092. <p></p>
  4093.  
  4094.  
  4095.  
  4096. <p>개인적으로 아직도 모니터링이 필요한데 하지 않고 있는 영역도 존재하고, 현재 모니터링 시스템을 더 잘 활용할 수 있는 여지가 한참 남아있다고 생각합니다. 그러나 이 일은 혼자 또는 일부 구성원들의 의지만으로는 잘 되기 어려울 것이라고 생각하기 때문에, 같은 뜻을 가지고 함께 해주실 동료분이 매우 중요합니다.</p>
  4097.  
  4098.  
  4099.  
  4100. <p>여느 대다수 회사 기술 블로그 포스트들의 결론이 그러하듯 저 또한 채용 홍보를 함으로써 마무리 지으려고 합니다.</p>
  4101.  
  4102.  
  4103.  
  4104. <p>현재 저희 상황을 최대한 자세하게 공유드림으로써 &#8220;이거 이렇게 하는 거 아닌데..&#8221; 라고 생각하시거나 <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f923.png" alt="🤣" class="wp-smiley" style="height: 1em; max-height: 1em;" />  &#8220;내 경험을 기반으로 기여할 수 있는 것이 많겠다&#8221; <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f62e.png" alt="😮" class="wp-smiley" style="height: 1em; max-height: 1em;" />  와 같은 생각을 가지신 분들께서 저희 리멤버에 합류해주시기를 간절히 기원합니다! <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f64f.png" alt="🙏" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f64f.png" alt="🙏" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f64f.png" alt="🙏" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  4105.  
  4106.  
  4107.  
  4108. <p></p>
  4109.  
  4110.  
  4111.  
  4112. <p><a href="https://hello.remember.co.kr/" target="_blank" rel="noreferrer noopener">리멤버팀에 합류하세요!!!</a></p>
  4113.  
  4114.  
  4115.  
  4116. <p></p>
  4117.  
  4118.  
  4119.  
  4120. <p>긴 글 끝까지 읽어주셔서 감사합니다.</p>
  4121.  
  4122.  
  4123.  
  4124. <p></p>
  4125. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2022/06/how-remember-monitors/">리멤버는 서비스 모니터링을 어떻게 하고 있을까?</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  4126. ]]></content:encoded>
  4127. <wfw:commentRss>https://blog.dramancompany.com/2022/06/how-remember-monitors/feed/</wfw:commentRss>
  4128. <slash:comments>6</slash:comments>
  4129. <post-id xmlns="com-wordpress:feed-additions:1">2967</post-id> </item>
  4130. </channel>
  4131. </rss>
  4132.  

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid RSS" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

http://www.feedvalidator.org/check.cgi?url=http%3A//blog.dramancompany.com/feed/

Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda