Sorry

This feed does not validate.

In addition, 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" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
  9. >
  10.  
  11. <channel>
  12. <title>DRAMA&amp;COMPANY</title>
  13. <atom:link href="https://blog.dramancompany.com/feed/" rel="self" type="application/rss+xml" />
  14. <link>https://blog.dramancompany.com</link>
  15. <description>DReam And MAke it happen</description>
  16. <lastBuildDate>Thu, 13 Feb 2020 02:39:33 +0000</lastBuildDate>
  17. <language>ko-KR</language>
  18. <sy:updatePeriod>
  19. hourly </sy:updatePeriod>
  20. <sy:updateFrequency>
  21. 1 </sy:updateFrequency>
  22. <generator>https://wordpress.org/?v=5.2.6</generator>
  23.  
  24. <image>
  25. <url>https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/11/cropped-symboltype_512x512.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>드라마앤컴퍼니 개발자 워크숍 후기</title>
  33. <link>https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/</link>
  34. <comments>https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/#respond</comments>
  35. <pubDate>Tue, 07 Jan 2020 01:35:58 +0000</pubDate>
  36. <dc:creator><![CDATA[Tom Kim]]></dc:creator>
  37. <category><![CDATA[기술 블로그]]></category>
  38. <category><![CDATA[개발문화]]></category>
  39. <category><![CDATA[개발자]]></category>
  40. <category><![CDATA[워크샵]]></category>
  41. <category><![CDATA[워크숍]]></category>
  42.  
  43. <guid isPermaLink="false">https://blog.dramancompany.com/?p=1312</guid>
  44. <description><![CDATA[<p>보통 회사들의 워크숍은 다음과 같은 순서로 진행됩니다. 회사의 희망찬 미래에 관한 PPT를 감상한다. 몸 쓰는 레크리에이션을 한다. 소주를 엄청 먹는다. 누군가 싸우거나 다친다 🤔 드라마앤컴퍼니에서 최근에 1박 2일 개발자 워크숍을 다녀왔는데 보통 회사들의 워크숍답지 않게 꽤 재밌고 유익한 시간을 보내서 워크숍의 내용을 공유 드려보고자 합니다. 워크숍은 3가지의 레크리에이션과 2가지의 프로그램으로 이루어졌습니다. 레크리에이션은 세 분이 준비해주셨고<a class="button" href="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/" title="Read More">Read more</a></p>
  45. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/">드라마앤컴퍼니 개발자 워크숍 후기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  46. ]]></description>
  47. <content:encoded><![CDATA[
  48. <p>보통 회사들의 워크숍은 다음과 같은 순서로 진행됩니다.</p>
  49.  
  50.  
  51.  
  52. <ol><li>회사의 희망찬 미래에 관한 PPT를 감상한다.</li><li>몸 쓰는 레크리에이션을 한다.</li><li>소주를 엄청 먹는다.</li><li>누군가 싸우거나 다친다 <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f914.png" alt="🤔" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li></ol>
  53.  
  54.  
  55.  
  56. <p>드라마앤컴퍼니에서 최근에 1박 2일 개발자 워크숍을 다녀왔는데 보통 회사들의 워크숍답지 않게 꽤 재밌고 유익한 시간을 보내서 워크숍의 내용을 공유 드려보고자 합니다.</p>
  57.  
  58.  
  59.  
  60. <p>워크숍은 3가지의 레크리에이션과 2가지의 프로그램으로 이루어졌습니다. 레크리에이션은 세 분이 준비해주셨고 프로그램은 1박 2일 워크숍을 먼저 제안해주신 분이 준비해주셨습니다. 참여 인원은 개발 관련 업무를 맡고 있는 12명이었습니다.</p>
  61.  
  62.  
  63.  
  64. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1354" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/collage2/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage2.jpg?fit=1200%2C600&amp;ssl=1" data-orig-size="1200,600" 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="collage2" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage2.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage2.jpg?resize=449%2C304&amp;ssl=1" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage2.jpg?resize=449%2C304&amp;ssl=1" alt="" class="wp-image-1354" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage2.jpg?w=1200&amp;ssl=1 1200w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage2.jpg?resize=768%2C384&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" /><figcaption>2층짜리 별장을 통으로 쓸 수 있었던 양평의 펜션</figcaption></figure></div>
  65.  
  66.  
  67.  
  68. <h2>#1 레크리에이션</h2>
  69.  
  70.  
  71.  
  72. <h3>#1-1 Scratch를 이용한 릴레이 프로그래밍</h3>
  73.  
  74.  
  75.  
  76. <p><a href="https://scratch.mit.edu/">Scratch</a>를 아시나요? Scratch는 아이들을 대상으로 그래픽 환경에서 쉽게 프로그래밍을 배울 수 있도록 해주는 언어 및 환경입니다. 어려운 코딩 없이 브라우저에서 드래그 앤 드롭으로 프로그래밍에 있는 로직을 구현할 수 있고 결과를 그래픽으로 바로 확인할 수 있습니다. 사이트에 들어가 보면 다른 사람들이 만들어둔 여러 프로젝트를 직접 실행해볼 수도 있고 소스 코드도 확인할 수 있습니다. 게임, 스토리, 애니메이션 등 다양한 그래픽 프로그래밍 결과물을 확인할 수 있습니다.</p>
  77.  
  78.  
  79.  
  80. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1313" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/screen-shot-2020-01-02-at-9-43-03/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?fit=1919%2C1272&amp;ssl=1" data-orig-size="1919,1272" 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="Screen Shot 2020-01-02 at 9.43.03" data-image-description="&lt;p&gt;Scratch 스크립트 화면 예시&lt;/p&gt;
  81. " data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?resize=449%2C304&amp;ssl=1" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?resize=449%2C304&#038;ssl=1" alt="Scratch 스크립트 화면 예시" class="wp-image-1313" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?resize=449%2C304&amp;ssl=1 449w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?zoom=2&amp;resize=449%2C304&amp;ssl=1 898w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-02-at-9.43.03.png?zoom=3&amp;resize=449%2C304&amp;ssl=1 1347w" sizes="(max-width: 449px) 100vw, 449px" data-recalc-dims="1" /><figcaption>Scratch 스크립트 화면 예시. 블록을 조합하여 코딩을 할 수 있다.</figcaption></figure></div>
  82.  
  83.  
  84.  
  85. <blockquote class="wp-block-quote"><p>“워크숍 저녁자리에서 테이블에 둘러앉아 즐겁게 술을 먹고 있는 사람들. 갑자기 한 명이 화장실을 가면서 한 자리가 비어있게 되었다.<br> 마침 새로운 테이블을 찾아 어슬렁거리던 재호님(aka CEO)에 눈에 띈 그 자리. 재호님은 그 자리로 향해 걸어오게 되는데…”</p></blockquote>
  86.  
  87.  
  88.  
  89. <figure class="wp-block-video aligncenter"><video controls src="https://blog.dramancompany.com/wp-content/uploads/2020/01/media.io_ScreenRecording2020-01-02at9.56.18-2.mp4"></video><figcaption>미리 구현된 애니메이션</figcaption></figure>
  90.  
  91.  
  92.  
  93. <p>첫 레크리에이션은 Scratch를 이용한 릴레이 코딩이었습니다. 레크리에이션 준비팀에서 미리 위와 같은 스토리를 Scratch를 이용하여 애니메이션처럼 구현해두셨고, 팀별로 한 명씩 돌아가면서 릴레이로 뒤 스토리를 구현하는 레크리에이션이었습니다. 5분 동안 Scratch에 익숙해질 수 있는 시간이 주어졌고, 바로 3분 간격으로 한 명씩 돌아가면서 스토리의 뒷부분을 구현했습니다.</p>
  94.  
  95.  
  96.  
  97. <p>Scratch의 컨셉에 대해서 대충 봤을 때는 “별거 없네~” 라고 생각하며 어떤 작품을 구현할까 들떠있던 분들 모두 막상 자기 차례가 되자 멘붕에 빠졌습니다.<br>블록을 이용하여 코딩하는 것이 낯설다 보니 기존에 있던 애니메이션 코드를 이해하는 데만도 많은 어려움이 있었습니다. 자기 차례가 오기 전까지는 “TDD 하고 계시죠?” 등의 여유로움을 보여주다가 본인의 차례 때는 3분 동안 아무것도 구현하지 못하고 당황하다가 뭐라도 해야겠다는 생각에 이것저것 건들다가 결국 끔찍한 결과물을 만들어내었습니다.<br>합의된 스토리가 아닌 개인의 스토리를 구현하신 분도 계셨고 게임을 만들다가 실패한 팀도 있는 등 생각하지 못했던 다양한 결과물이 나왔습니다.<br>어쩌면 개발자 워크숍에서만 가능할지도 모르는 레크리에이션으로 평소 업무용 코딩에서는 느끼지 못했던 재미를 느낄 수 있었습니다.</p>
  98.  
  99.  
  100.  
  101. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1324" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/kakaotalk_image_2020-01-02-12-51-54/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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;1&quot;}" data-image-title="KakaoTalk_Image_2020-01-02-12-51-54" data-image-description="&lt;p&gt;흔한 집중하는 개발자의 자세&lt;/p&gt;
  102. " data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?resize=449%2C304&amp;ssl=1" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?resize=449%2C304&#038;ssl=1" alt="흔한 집중하는 개발자의 자세" class="wp-image-1324" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?resize=449%2C304&amp;ssl=1 449w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?zoom=2&amp;resize=449%2C304&amp;ssl=1 898w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/KakaoTalk_Image_2020-01-02-12-51-54.jpeg?zoom=3&amp;resize=449%2C304&amp;ssl=1 1347w" sizes="(max-width: 449px) 100vw, 449px" data-recalc-dims="1" /><figcaption>흔한 집중하는 개발자의 자세</figcaption></figure></div>
  103.  
  104.  
  105.  
  106. <h3>#1-2 동료 얼굴 부위 보고 맞추기</h3>
  107.  
  108.  
  109.  
  110. <p>두 번째 레크리에이션으로는 “덕질하는 연예인은 귀만 봐도 알아볼 수 있다” 등의 놀이로 유명한 &#8220;얼굴 부위 보고 맞추기&#8221; 게임을 진행했습니다. 다음과 같이 동료 사진 중 얼굴의 일부분만 보고 누군지 알아맞히는 게임입니다. (하단 좌측이 문제, 오른쪽이 정답입니다.)</p>
  111.  
  112.  
  113.  
  114. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-jetpack-tiled-gallery aligncenter is-style-rectangular"><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__gallery"><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__row"><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__col"><figure class="tiled-gallery__item"><img data-attachment-id="1330" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/screen-shot-2020-01-05-at-5-17-55-pm/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?fit=3360%2C2100&amp;ssl=1" data-orig-size="3360,2100" 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="Screen Shot 2020-01-05 at 5.17.55 PM" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?resize=449%2C304&amp;ssl=1" data-attachment-id="1330" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/screen-shot-2020-01-05-at-5-17-55-pm/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?fit=3360%2C2100&amp;ssl=1" data-orig-size="3360,2100" 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="Screen Shot 2020-01-05 at 5.17.55 PM" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?resize=449%2C304&amp;ssl=1" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?strip=all&#038;w=600&#038;ssl=1 600w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?strip=all&#038;w=900&#038;ssl=1 900w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?strip=all&#038;w=1200&#038;ssl=1 1200w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?strip=all&#038;w=1500&#038;ssl=1 1500w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?strip=all&#038;w=1800&#038;ssl=1 1800w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?strip=all&#038;w=2000&#038;ssl=1 2000w" alt="" data-height="2100" data-id="1330" data-link="https://blog.dramancompany.com/?attachment_id=1330" data-url="https://blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png" data-width="3360" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.55-PM.png?ssl=1"/></figure></div><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__col"><figure class="tiled-gallery__item"><img data-attachment-id="1331" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/screen-shot-2020-01-05-at-5-17-57-pm/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?fit=3360%2C2100&amp;ssl=1" data-orig-size="3360,2100" 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="Screen Shot 2020-01-05 at 5.17.57 PM" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?resize=449%2C304&amp;ssl=1" data-attachment-id="1331" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/screen-shot-2020-01-05-at-5-17-57-pm/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?fit=3360%2C2100&amp;ssl=1" data-orig-size="3360,2100" 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="Screen Shot 2020-01-05 at 5.17.57 PM" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?resize=449%2C304&amp;ssl=1" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?strip=all&#038;w=600&#038;ssl=1 600w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?strip=all&#038;w=900&#038;ssl=1 900w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?strip=all&#038;w=1200&#038;ssl=1 1200w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?strip=all&#038;w=1500&#038;ssl=1 1500w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?strip=all&#038;w=1800&#038;ssl=1 1800w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?strip=all&#038;w=2000&#038;ssl=1 2000w" alt="" data-height="2100" data-id="1331" data-link="https://blog.dramancompany.com/?attachment_id=1331" data-url="https://blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png" data-width="3360" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/Screen-Shot-2020-01-05-at-5.17.57-PM.png?ssl=1"/></figure></div></div></div></div>
  115.  
  116.  
  117.  
  118. <p>워크숍에 참석하신 분들만 사진의 대상이었기 때문에 모두가 엄청 쉬울 거라 예상했지만…. 이것 또한 쉽지 않았습니다. 총 40개의 문제가 준비됐고 자기도 자기 자신의 부위를 보고 전혀 못 맞추는 경우가 허다했습니다. 몇 년 전 사진까지 찾으셔서 문제를 제출해주셨는데 스피드 퀴즈와 같은 긴장감과 재미를 둘 다 잡은 게임이었습니다.</p>
  119.  
  120.  
  121.  
  122. <h3>#1-3 마시멜로 챌린지</h3>
  123.  
  124.  
  125.  
  126. <p>마지막 레크리에이션은 유치원생이 하버드 MBA 학생들보다 더 잘한다고 유명한 게임으로 팀 빌딩에 자주 이용되는 마시멜로 챌린지였습니다.<br>제한된 수의 마시멜로, 스파게티 가닥, 종이테이프를 이용하여 정해진 시간 동안 가장 높은 탑을 쌓는 게임입니다. 저희 팀도 하버드 MBA 학생들이었을까요… 구글링을 통하여 최적의 솔루션을 검색하여 최고의 결과물을 만들려고 스파게티를 두 가닥씩 겹쳐서 만들었지만, 제한시간을 고려하지 못했었습니다. 10분이라는 제한 시간이 있었고 결국 바닥을 쌓는데 시간 대부분을 허비하여 막판에 급하게 높이 쌓아보려 했으나 다른 팀보다 낮은 높이로 만들 수밖에 없었습니다. 오히려 큰 고민 없이 바로 쌓기 시작했던 팀이 더 높이 쌓을 수 있었습니다.</p>
  127.  
  128.  
  129.  
  130. <p>마시멜로 챌린지에서 유치원생이 성인보다 더 높은 성적을 거두는 이유는 다음과 같다고 합니다. MBA 학생들뿐만 아니라 대부분 성인은 마시멜로나 스파게티를 건들기 전에 방향설정, 구체적인 계획 구상 등에 대한 논의를 진행합니다. 그렇게 나온 한 가지 계획을 세운 뒤에야 실제 행동에 옮기고 끝까지 그 작전을 따라갑니다. 반면에 유치원생들은 처음부터 각자 많은 시도를 해보면서 실패를 여러 번 해보고 더 좋은 방식을 빨리 찾아내기 때문에 더 좋은 결과를 만들어낸다고 합니다. 자세한 내용은 <a href="https://www.ted.com/talks/tom_wujec_build_a_tower_build_a_team?language=ko#t-354667">톰 워젝의 TED 영상</a>에서 확인하실 수 있습니다.</p>
  131.  
  132.  
  133.  
  134. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-jetpack-tiled-gallery aligncenter is-style-rectangular"><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__gallery"><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__row"><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__col"><figure class="tiled-gallery__item"><img data-attachment-id="1278" data-permalink="https://blog.dramancompany.com/img_0298/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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_0298" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?resize=449%2C304&amp;ssl=1" data-attachment-id="1278" data-permalink="https://blog.dramancompany.com/img_0298/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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_0298" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?resize=449%2C304&amp;ssl=1" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?strip=all&#038;w=600&#038;ssl=1 600w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?strip=all&#038;w=900&#038;ssl=1 900w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?strip=all&#038;w=1200&#038;ssl=1 1200w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?strip=all&#038;w=1500&#038;ssl=1 1500w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?strip=all&#038;w=1800&#038;ssl=1 1800w,https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?strip=all&#038;w=2000&#038;ssl=1 2000w" alt="" data-height="4032" data-id="1278" data-link="https://blog.dramancompany.com/?attachment_id=1278" data-url="https://blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg" data-width="3024" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0298.jpg?ssl=1"/></figure></div><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__col"><figure class="tiled-gallery__item"><img data-attachment-id="1279" data-permalink="https://blog.dramancompany.com/img_0303/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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_0303" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?resize=449%2C304&amp;ssl=1" data-attachment-id="1279" data-permalink="https://blog.dramancompany.com/img_0303/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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_0303" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?resize=449%2C304&amp;ssl=1" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?strip=all&#038;w=600&#038;ssl=1 600w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?strip=all&#038;w=900&#038;ssl=1 900w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?strip=all&#038;w=1200&#038;ssl=1 1200w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?strip=all&#038;w=1500&#038;ssl=1 1500w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?strip=all&#038;w=1800&#038;ssl=1 1800w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?strip=all&#038;w=2000&#038;ssl=1 2000w" alt="" data-height="4032" data-id="1279" data-link="https://blog.dramancompany.com/?attachment_id=1279" data-url="https://blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg" data-width="3024" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_0303.jpg?ssl=1"/></figure></div><div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="tiled-gallery__col"><figure class="tiled-gallery__item"><img data-attachment-id="1280" data-permalink="https://blog.dramancompany.com/img_1456/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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_1456" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?resize=449%2C304&amp;ssl=1" data-attachment-id="1280" data-permalink="https://blog.dramancompany.com/img_1456/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?fit=3024%2C4032&amp;ssl=1" data-orig-size="3024,4032" 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_1456" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?resize=449%2C304&amp;ssl=1" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?strip=all&#038;w=600&#038;ssl=1 600w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?strip=all&#038;w=900&#038;ssl=1 900w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?strip=all&#038;w=1200&#038;ssl=1 1200w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?strip=all&#038;w=1500&#038;ssl=1 1500w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?strip=all&#038;w=1800&#038;ssl=1 1800w,https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?strip=all&#038;w=2000&#038;ssl=1 2000w" alt="" data-height="4032" data-id="1280" data-link="https://blog.dramancompany.com/?attachment_id=1280" data-url="https://blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg" data-width="3024" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/11/IMG_1456.jpg?ssl=1"/></figure></div></div></div></div>
  135.  
  136.  
  137.  
  138. <p>워크숍 이후에는 두 가지 프로그램이 준비되어 있었습니다.</p>
  139.  
  140.  
  141.  
  142. <h2>#2 프로그램</h2>
  143.  
  144.  
  145.  
  146. <h3>#2-1 롤 플레잉 시뮬레이션 게임 – 스도쿠 맥스</h3>
  147.  
  148.  
  149.  
  150. <p>스도쿠 맥스는 SRPG(Simulation Role-playing Game)입니다. 제한된 시간과 정해진 규칙으로 여러명이 각자 특정 롤을 맡고 플레이하는 게임입니다. 시간과 규칙이 정해진 특수한 상황 때문에 플레이어들은 몰입하다 보면 개인의 성격이 과장되어 나타나게 됩니다. 그런 모습들을 옵저버들이 관찰한 뒤, 나중에 공유하는 게임입니다. 이를 통하여 평소 협업하는 동료 그리고 자신이 평소에 어떤 성향을 갖고 일을 하고 있었는지를 객관적으로 알아볼 수 있습니다.<br>다양한 SRPG 게임이 존재하는데 저희가 진행했던 게임은 스도쿠 맥스입니다. 간단히 규칙을 설명 드리면 다음과 같습니다.</p>
  151.  
  152.  
  153.  
  154. <ul><li>게임을 진행하는 시장 1명, 게임의 규칙을 지키는 경찰 1명, 팀마다 구성원의 행동을&nbsp; 관</li><li>찰하는 옵저버가 1명씩 존재한다.</li><li>각 팀은 하나의 회사가 되며 회사에서 CEO를 선출해야 한다.</li><li>각 팀에게는 같은 스도쿠 문제지를 주며 스도쿠의 숫자를 하나씩 맞출 때마다 돈을 벌 수 있다.</li><li>모든 규칙을 설명해주지는 않고 일부 규칙만 설명해주고 나머지는 게임을 진행하면서 알아간다.</li></ul>
  155.  
  156.  
  157.  
  158. <p>이 외에도 돈을 벌 수 있는 다른 방법이나 해선 안되는 제약 사항들이 있습니다. 저희는 6명으로 구성된 팀을 두 개 만들어서 진행했습니다. 시장은 게임 진행자의 역할이고 옵저버는 로그를 남기듯 각 팀의 구성원들이 어떤 행동, 대사, 감정을 표현하는지 모두 상세하게 기록합니다. 구성원의 말투 등 감정 표현까지도 함께 기록합니다. 구성원들은 게임에 집중하느라 타인의 시선을 신경 쓰지 않고 본인의 모습을 그대로 보여주게 되고 옵저버들을 그 모습들로 인해 이 팀에서는 어떤 현상이 일어났는지 관찰합니다.</p>
  159.  
  160.  
  161.  
  162. <p>예상했던대로 모든 분이 게임에 엄청나게 빨리 몰입을 해주셨고 계획대로 사람들의 본 모습을 확인할 수 있었습니다. 게임이 모두 종료된 후에는 옵저버 분들이 자기가 팀들에 대해서 기록하고 얻은 인사이트들을 공유해주셨습니다.</p>
  163.  
  164.  
  165.  
  166. <p>양 팀에서 회사의 CEO의 역할을 하는 사람마다 다른 방식으로 의사결정을 내리는 것, 사람들끼리 협업을 하는 방법, 의견 충돌이 있을 때 서로 해결하는 방법 등 같은 게임이었지만 모두 다양한 방식으로 문제를 해결하는 것을 알 수 있었습니다.</p>
  167.  
  168.  
  169.  
  170. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1346" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/ezgif-6-cda27509f0c9-2/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?fit=4032%2C3024&amp;ssl=1" data-orig-size="4032,3024" 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;1&quot;}" data-image-title="ezgif-6-cda27509f0c9" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?resize=449%2C304&amp;ssl=1" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?resize=449%2C304&amp;ssl=1" alt="" class="wp-image-1346" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?w=4032&amp;ssl=1 4032w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?resize=768%2C576&amp;ssl=1 768w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?w=2340&amp;ssl=1 2340w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/ezgif-6-cda27509f0c9.jpg?w=3510&amp;ssl=1 3510w" sizes="(max-width: 1170px) 100vw, 1170px" /><figcaption>적극적으로 시장님을 설득하는 CEO</figcaption></figure></div>
  171.  
  172.  
  173.  
  174. <h3>#2-2 동료 알아보기</h3>
  175.  
  176.  
  177.  
  178. <p>마지막 프로그램에서는 두 명씩 짝지어 마주 보고 앉은 뒤 서로 상대방의 자기소개를 작성해주는 시간을 가졌습니다. 본인의 자기소개가 아니라 상대방의 자기소개이다 보니 평소에 자신이 상대방을 어떻게 생각하고 있는지 고민하게 되었습니다. 기존에 알고 있던 정보 외 추가 정보를 얻을 수 있도록 3가지의 질문도 할 수 있었습니다. 그 외에도 워크숍에 참여하기 이전에 각자 진행한 MBTI 테스트 결과를 비교하기도 하고 서로의 얼굴을 그려주는 시간도 가졌습니다. 이런 시간을 통해 동료에게 평소 알 수 없었던 새로운 사실도 알고 훨씬 친해질 수 있었습니다.</p>
  179.  
  180.  
  181.  
  182. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1353" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/img_20191115_172424/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?fit=4000%2C3000&amp;ssl=1" data-orig-size="4000,3000" 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_20191115_172424" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?resize=449%2C304&amp;ssl=1" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?resize=449%2C304&amp;ssl=1" alt="" class="wp-image-1353" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?w=4000&amp;ssl=1 4000w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?resize=768%2C576&amp;ssl=1 768w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?w=2340&amp;ssl=1 2340w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191115_172424.jpg?w=3510&amp;ssl=1 3510w" sizes="(max-width: 1170px) 100vw, 1170px" /><figcaption>그리고 있는 그림을 보지 않고 서로의 얼굴을 그려줘야 한다.</figcaption></figure></div>
  183.  
  184.  
  185.  
  186. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1355" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/img_20191116_093936/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?fit=3000%2C4000&amp;ssl=1" data-orig-size="3000,4000" 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_20191116_093936" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?resize=449%2C304&amp;ssl=1" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?resize=449%2C304&#038;ssl=1" alt="" class="wp-image-1355" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?resize=449%2C304&amp;ssl=1 449w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?zoom=2&amp;resize=449%2C304&amp;ssl=1 898w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_20191116_093936.jpg?zoom=3&amp;resize=449%2C304&amp;ssl=1 1347w" sizes="(max-width: 449px) 100vw, 449px" data-recalc-dims="1" /><figcaption>MBTI 테스트 결과, 자기 소개 그리고 끔찍한 그림 실력</figcaption></figure></div>
  187.  
  188.  
  189.  
  190. <h3>#3 저녁 식사 및 음주</h3>
  191.  
  192.  
  193.  
  194. <p>뭐니 뭐니 해도 워크숍의 마지막은 맛있는 음식과 술이겠죠?<br>저녁 식사 때는 바비큐 외에도 감바스, 파스타, 스탠딩 바 등 다양한 음식들을 통해 배부르게 먹을 수 있었습니다. 그 외에도 에어프라이어가 예상 밖의 MVP가 될 정도로 중요한 역할을 해냈습니다. 워크숍에 갔을 당시 인싸들의 조합인 홈런볼뿐만 아니라 온갖 음식들을 다 구워 먹었습니다. </p>
  195.  
  196.  
  197.  
  198. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter is-resized"><img data-attachment-id="1337" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/collage/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage.jpg?fit=1200%2C1200&amp;ssl=1" data-orig-size="1200,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="collage" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage.jpg?resize=449%2C304&amp;ssl=1" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage.jpg?resize=449%2C304&amp;ssl=1" alt="" class="wp-image-1337" width="518" height="351" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage.jpg?resize=449%2C304&amp;ssl=1 449w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/collage.jpg?zoom=2&amp;resize=518%2C351&amp;ssl=1 1036w" sizes="(max-width: 518px) 100vw, 518px" /><figcaption>예상 밖의 MVP였던 에어프라이어</figcaption></figure></div>
  199.  
  200.  
  201.  
  202. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1338" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/img_0362-2/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?fit=4032%2C3024&amp;ssl=1" data-orig-size="4032,3024" 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_0362" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?resize=449%2C304&amp;ssl=1" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?resize=449%2C304&amp;ssl=1" alt="" class="wp-image-1338" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?w=4032&amp;ssl=1 4032w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?resize=768%2C576&amp;ssl=1 768w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?w=2340&amp;ssl=1 2340w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0362.jpg?w=3510&amp;ssl=1 3510w" sizes="(max-width: 1170px) 100vw, 1170px" /><figcaption>성민님의 SM바</figcaption></figure></div>
  203.  
  204.  
  205.  
  206. <div data-carousel-extra='{"blog_id":1,"permalink":"https:\/\/blog.dramancompany.com\/2020\/01\/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0\/"}' class="wp-block-image"><figure class="aligncenter"><img data-attachment-id="1339" data-permalink="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/img_0331-2/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?fit=3088%2C2316&amp;ssl=1" data-orig-size="3088,2316" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;2.2&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;iPhone 11 Pro&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;1573844100&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;2.71&quot;,&quot;iso&quot;:&quot;400&quot;,&quot;shutter_speed&quot;:&quot;0.025&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;6&quot;}" data-image-title="IMG_0331" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?resize=449%2C304&amp;ssl=1" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?resize=449%2C304&amp;ssl=1" alt="" class="wp-image-1339" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?w=3088&amp;ssl=1 3088w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?resize=768%2C576&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2020/01/IMG_0331.jpg?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" /></figure></div>
  207.  
  208.  
  209.  
  210. <h2>마무리</h2>
  211.  
  212.  
  213.  
  214. <p>글을 너무 교육 중심적인 관점에서 쓰다 보니 살짝 노잼 워크숍이 아니었을까 생각하실 수 있겠지만 가볍고 재미있는 분위기로 진행됐었습니다. 워크숍 이후 만족도 조사에서 압도적으로 긍정적인 평가를 받고 또다시 가고 싶다는 의견도 많이 있었습니다. 1박 2일 워크숍은 지금까지 회사에서 거의 진행해본 적이 없어서 걱정되었지만 알찬 프로그램을 준비해주신 분들 덕분에 보람차고 재미있는 워크숍을 경험할 수 있었습니다&nbsp;<img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f601.png" alt="😁" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  215. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/">드라마앤컴퍼니 개발자 워크숍 후기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  216. ]]></content:encoded>
  217. <wfw:commentRss>https://blog.dramancompany.com/2020/01/%eb%93%9c%eb%9d%bc%eb%a7%88%ec%95%a4%ec%bb%b4%ed%8d%bc%eb%8b%88-%ea%b0%9c%eb%b0%9c%ec%9e%90-%ec%9b%8c%ed%81%ac%ec%88%8d-%ed%9b%84%ea%b8%b0/feed/</wfw:commentRss>
  218. <slash:comments>0</slash:comments>
  219. <enclosure url="https://blog.dramancompany.com/wp-content/uploads/2020/01/media.io_ScreenRecording2020-01-02at9.56.18-2.mp4" length="1921814" type="video/mp4" />
  220. <post-id xmlns="com-wordpress:feed-additions:1">1312</post-id> </item>
  221. <item>
  222. <title>AWS로 서버 없이 웹 서비스 운영하기 &#8211; 1</title>
  223. <link>https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/</link>
  224. <comments>https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/#comments</comments>
  225. <pubDate>Thu, 05 Sep 2019 10:59:45 +0000</pubDate>
  226. <dc:creator><![CDATA[박 명호]]></dc:creator>
  227. <category><![CDATA[기술 블로그]]></category>
  228. <category><![CDATA[AWS]]></category>
  229. <category><![CDATA[Code Deploy]]></category>
  230. <category><![CDATA[배포]]></category>
  231.  
  232. <guid isPermaLink="false">http://blog.dramancompany.com/?p=1081</guid>
  233. <description><![CDATA[<p>최근 드라마앤컴퍼니에서는 리멤버 커리어라는 구직자와 리쿠르터를 연결해주는 서비스를 출시하였습니다 🙂 저는 리멤버 커리어 프로젝트를 진행하면서 S3, CloudFront, Route53, CodePipeline, CodeBuild, [email protected]를 사용하여 웹 서비스 배포, 배포 자동화 구축, Server Side Rendering 없이 SEO하기 등 다양한 작업을 진행하였는데요, 리멤버 커리어를 만들면서 경험한 것들을 글로 옮겨 서버 없이 웹을 배포하려고 하는 사람들에게 도움이 되고자 글을 작성하게 되었습니다. 이번 글에서는<a class="button" href="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/" title="Read More">Read more</a></p>
  234. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/">AWS로 서버 없이 웹 서비스 운영하기 &#8211; 1</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  235. ]]></description>
  236. <content:encoded><![CDATA[<p>최근 드라마앤컴퍼니에서는<strong> <a href="https://career.rememberapp.co.kr/talent">리멤버 커리어</a></strong>라는 구직자와 리쿠르터를 연결해주는 서비스를 출시하였습니다 <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  237. <p>저는<strong> 리멤버 커리어</strong> 프로젝트를 진행하면서 S3, CloudFront, Route53, CodePipeline, CodeBuild, [email protected]를 사용하여 웹 서비스 배포, 배포 자동화 구축, Server Side Rendering 없이 SEO하기 등 다양한 작업을 진행하였는데요, 리멤버 커리어를 만들면서 경험한 것들을 글로 옮겨 서버 없이 웹을 배포하려고 하는 사람들에게 도움이 되고자 글을 작성하게 되었습니다.</p>
  238. <p>이번 글에서는 서버리스 아키텍쳐의 필요성에 대해 간략히 공유하고, <strong>S3</strong>와 <strong>CloudFront</strong>, <strong>Route53</strong>을 이용해 서버 없이 React Project를 배포하는 방법에 대해 얘기해보도록 하겠습니다.</p>
  239. <h1>서버리스 아키텍쳐의 필요성</h1>
  240. <p>웹 서버가 존재한다는 것은 서버 관리 비용 또한 존재한다는 것을 의미합니다. 작게는 OS 보안 업데이트에 따른 새로운 AMI 생성부터 크게는 EC2 인스턴스 장애 해결까지 다양한 관리 비용 생깁니다. 드라마앤컴퍼니에서는 DevOps 엔지니어가 따로 존재하지 않고 Server/Web 팀에서 자신이 개발하는 프로젝트의 코드뿐만 아니라 인프라도 함께 유지보수 및 관리를 하고 있기 때문에 <strong>서버 관리 비용이 늘어날수록 서비스 개발 속도에 제동</strong>이 걸리는 문제가 있습니다.</p>
  241. <p>그렇기 때문에 더욱 서버리스 아키텍쳐를 선택할 수 밖에 없었는데, 서버리스 아키텍쳐로 서비스를 운영한다는 것은 서버 관리에 대한 대부분을 Cloud Service 사업자, 즉 AWS가 많은 부분을 관리해 준다는 것이고, 이러한 장점은 <strong>개발자가 코드를 작성하는 것에 더 많은 시간을 투자 </strong>할 수 있게 도와준다는 것을 의미합니다.</p>
  242. <p>또한, 관리 비용 측면 이외에도 <strong>가격이 저렴</strong>하다는 장점도 있는데요, AWS에서 제공하는 비용 계산기로 아주 간단하게 기존 리멤버에서 사용하던 Instance 사양과 가격 그리고 리멤버 커리어의 비용을 비교해 보았습니다.</p>
  243. <p><div id="attachment_1091" style="width: 1874px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?ssl=1"><img aria-describedby="caption-attachment-1091" data-attachment-id="1091" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-03-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-3-11-39/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?fit=1864%2C258&amp;ssl=1" data-orig-size="1864,258" 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="스크린샷 2019-09-03 오후 3.11.39" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?resize=449%2C258&amp;ssl=1" class="size-full wp-image-1091" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?resize=1170%2C162&#038;ssl=1" alt="" width="1170" height="162" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?w=1864&amp;ssl=1 1864w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.11.39.png?resize=768%2C106&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a><p id="caption-attachment-1091" class="wp-caption-text">리멤버 서비스에서 실제로 사용중인 t2.medium 2대 기준 24시간 한달 비용 $89.02 (트래픽 증가시 +a 금액 있음)</p></div></p>
  244. <p><div id="attachment_1093" style="width: 2550px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?ssl=1"><img aria-describedby="caption-attachment-1093" data-attachment-id="1093" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-03-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-3-17-44/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?fit=2540%2C390&amp;ssl=1" data-orig-size="2540,390" 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="스크린샷 2019-09-03 오후 3.17.44" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?resize=449%2C304&amp;ssl=1" class="size-full wp-image-1093" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?resize=1170%2C180&#038;ssl=1" alt="" width="1170" height="180" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?w=2540&amp;ssl=1 2540w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?resize=768%2C118&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-3.17.44.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a><p id="caption-attachment-1093" class="wp-caption-text">S3 1G 적재 및 100만 request, CloudFront 월 1G Data transfer 기준 ([email protected]는 포함하지 않음)</p></div></p>
  245. <p>리멤버에서 실제로 사용하고 있는 t2.medium 인스턴스 2대의 한 달 가격은 <strong>매달 89달러</strong>의 비용이 들지만 서버리스 아키텍쳐로 구성한 리멤버 커리어의 가격을 간단히 계산해보면 <strong>약 1/200의 비용</strong>으로 한 달을 운영 할 수 있다는 것을 알 수 있습니다.</p>
  246. <h1>서버리스 아키텍쳐로 웹 배포하기</h1>
  247. <p><div id="attachment_1097" style="width: 594px" class="wp-caption aligncenter"><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Career-web_Infra_1.png?ssl=1"><img aria-describedby="caption-attachment-1097" data-attachment-id="1097" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/career-web_infra_1/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Career-web_Infra_1.png?fit=584%2C121&amp;ssl=1" data-orig-size="584,121" 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="Career-web_Infra_(1)" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Career-web_Infra_1.png?resize=290%2C121&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Career-web_Infra_1.png?resize=449%2C121&amp;ssl=1" class="wp-image-1097 size-full" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Career-web_Infra_1.png?resize=584%2C121&#038;ssl=1" alt="" width="584" height="121" data-recalc-dims="1" /></a><p id="caption-attachment-1097" class="wp-caption-text">예제를 통해 완성될 인프라 구조</p></div></p>
  248. <p>앞에서도 얘기했듯이 <strong>리멤버 커리어</strong>는 S3와 CloudFront 그리고 Route53을 기본으로 사용하여 서비스하고 있는데요, 리멤버 커리어 서비스를 만든 방법 그대로 S3 Bucket 생성부터 CloudFront Distribution 생성, Route53 연동까지 스크린샷과 설명을 통해 하나씩 살펴보도록 하겠습니다 <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  249. <ul>
  250. <li>이 예제에서는 <strong>CRA(create-react-app)</strong>로 만든 기본 App을 이용합니다.</li>
  251. <li>CRA로 만든 초기 코드에 <strong>react-router-dom</strong>을 이용하여 <strong>/test </strong>route를 추가하였습니다.</li>
  252. </ul>
  253. <h2>1. S3 Bucket만들기</h2>
  254. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?ssl=1"><img data-attachment-id="1099" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-16-43/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?fit=2186%2C1546&amp;ssl=1" data-orig-size="2186,1546" 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="스크린샷 2019-09-02 오후 5.16.43" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?resize=449%2C304&amp;ssl=1" class="aligncenter wp-image-1099 " src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?resize=674%2C476&#038;ssl=1" alt="" width="674" height="476" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?w=2186&amp;ssl=1 2186w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?resize=768%2C543&amp;ssl=1 768w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.16.43.png?resize=211%2C150&amp;ssl=1 211w" sizes="(max-width: 674px) 100vw, 674px" data-recalc-dims="1" /></a></p>
  255. <p>AWS S3에 들어가 버킷 생성을 누른 후 버킷의 이름을 설정합니다. 버킷의 이름은 원하는 이름으로 생성하면 되지만 추후 사용할 Domain을 그대로 사용하는 것이 관리에 용이합니다. 버킷의 옵션들은 따로 설정하지 않고 진행하겠습니다.</p>
  256. <h2>2. S3 Bucket에 React Build File Upload 하기</h2>
  257. <p><div id="attachment_1100" style="width: 3164px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?ssl=1"><img aria-describedby="caption-attachment-1100" data-attachment-id="1100" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-28-23/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?fit=3154%2C1544&amp;ssl=1" data-orig-size="3154,1544" 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="스크린샷 2019-09-02 오후 5.28.23" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?resize=449%2C304&amp;ssl=1" class="size-full wp-image-1100" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?resize=1170%2C573&#038;ssl=1" alt="" width="1170" height="573" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?w=3154&amp;ssl=1 3154w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?resize=768%2C376&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.28.23.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a><p id="caption-attachment-1100" class="wp-caption-text">yarn build를 통해 build된 파일들을 S3에 업로드한 모습</p></div></p>
  258. <p>버킷을 생성하셨다면 로컬에서 Build 한 React app을 업로드 해주어야 합니다.</p>
  259. <p>업로드가 완료되었다면 CloudFront Distribution을 생성해봅시다.</p>
  260. <h2>3. CloudFront Distribution 생성하기</h2>
  261. <p><a href="https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Introduction.html">Amazon CloudFront</a>는 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 CDN 서비스이며 CloudFront는 엣지 로케이션이라고 하는 데이터 센터를 통해 사용자에게 빠르게 콘텐츠를 전달해 줄 수 있습니다. 또한 CloudFront를 사용해야만 SSL 인증서를 사용할 수 있습니다. 그러면 바로 생성을 해보도록 하겠습니다. CloudFront Dashboard에 들어가서 Create Distribution 버튼을 눌러 Distribution을 만들 준비를 합니다.</p>
  262. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?ssl=1"><img data-attachment-id="1101" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-33-59/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?fit=2782%2C1092&amp;ssl=1" data-orig-size="2782,1092" 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="스크린샷 2019-09-02 오후 5.33.59" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?resize=449%2C304&amp;ssl=1" class="aligncenter size-full wp-image-1101" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?resize=1170%2C459&#038;ssl=1" alt="" width="1170" height="459" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?w=2782&amp;ssl=1 2782w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?resize=768%2C301&amp;ssl=1 768w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.33.59.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  263. <p>저희는 Web을 배포할 것이기 때문에 Web의 Get Started를 눌러 다음 단계로 넘어가 주세요.</p>
  264. <h3>Origin Settings</h3>
  265. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?ssl=1"><img data-attachment-id="1102" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-36-18/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?fit=2796%2C1002&amp;ssl=1" data-orig-size="2796,1002" 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="스크린샷 2019-09-02 오후 5.36.18" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?resize=449%2C304&amp;ssl=1" class="aligncenter size-full wp-image-1102" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?resize=1170%2C419&#038;ssl=1" alt="" width="1170" height="419" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?w=2796&amp;ssl=1 2796w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?resize=768%2C275&amp;ssl=1 768w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.18.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  266. <p>가장 먼저 보이는 Origin Setting에서는 Origin Server에 대한 설정을 해줄 수 있습니다.</p>
  267. <ul>
  268. <li><strong>Origin Domain Name</strong>을 세팅해줍니다.<br />
  269. Origin Domain은 CloudFront가 web content를 받아 올 서버의 Domain을 뜻하며 우리가 만들었던 S3의 버킷에서 content들을 받아와야 하므로 아까 만들어둔 S3 Bucket의 Domain을 찾아 설정해줍니다. 자동완성이 되기 때문에 쉽게 찾을 수 있습니다.</li>
  270. </ul>
  271. <p>다음은 보안 설정을 해주어야 합니다. 해당 설정을 통해 원치 않는 경로로 Bucket Object에 접근하는 요청을 막을 수 있습니다. (ex. S3 Domain을 알아내서 특정 파일을 탈취)</p>
  272. <ul>
  273. <li><strong>Restrict Bucket Access​</strong>를 <strong>yes</strong>로 만들어 줍니다. 이 설정을 키게 되면 S3 Domain으로 직접 접근하는 요청을 막아주고 Cloudfront에서 정해진 규칙에 맞는 요청만 Bucket의 Object에 접근 할 수 있도록 해줍니다. 이 정해진 규칙에는 signed cookies나 signed URL 그리고 OAI(Origin Access Identity)가 있고 이 중에서 저희는 OAI를 이용하여 설정할 예정입니다.</li>
  274. <li><strong>Origin Access Identity</strong> 설정에서 <strong>Create a New Identity</strong>를 선택합니다</li>
  275. <li><strong>Grant Read Permissions on Bucket</strong> 설정에서 <strong>Yes, Update Bucket Policy</strong>를 선택합니다. 이렇게 되면 OAI가 자동으로 생성되며 S3의 Buckey Policy에 해당 OAI를 가진 User만 (이 경우엔 Cloudfront) Bucket의 Object에 접근하도록 자동으로 설정을 해줍니다.</li>
  276. </ul>
  277. <h3>Default Cache Behavior Settings</h3>
  278. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?ssl=1"><img data-attachment-id="1103" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-36-49/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?fit=1694%2C1482&amp;ssl=1" data-orig-size="1694,1482" 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="스크린샷 2019-09-02 오후 5.36.49" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?resize=449%2C304&amp;ssl=1" class="aligncenter wp-image-1103" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?resize=629%2C550&#038;ssl=1" alt="" width="629" height="550" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?w=1694&amp;ssl=1 1694w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-5.36.49.png?resize=768%2C672&amp;ssl=1 768w" sizes="(max-width: 629px) 100vw, 629px" data-recalc-dims="1" /></a></p>
  279. <p>Default Cache Behavior Settings에서는 Path Pattern을 눈여겨봐야 합니다. Default로 설정이 되어있고 이는 바꿀 수 없는데요(Distribution 생성 후 Behavior 추가 가능), 모든 path의 요청에 대해서 Cloudfront가 Request에 대해 어떠한 처리를 할 것인지 설정할 수 있습니다.</p>
  280. <ul>
  281. <li><strong>Viewer Protocol Policy</strong>를 <strong>Redirect HTTP to HTTPS</strong>로 선택해줍니다.</li>
  282. </ul>
  283. <h3>Distribution Setting<a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?ssl=1"><img data-attachment-id="1104" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-6-23-30/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?fit=2394%2C2004&amp;ssl=1" data-orig-size="2394,2004" 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="스크린샷 2019-09-02 오후 6.23.30" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?resize=449%2C304&amp;ssl=1" class="aligncenter size-full wp-image-1104" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?resize=1170%2C979&#038;ssl=1" alt="" width="1170" height="979" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?w=2394&amp;ssl=1 2394w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?resize=768%2C643&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-6.23.30.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></h3>
  284. <p>Distribution Setting에서는 CloudFront 자체에 대해서 설정을 해줄 수 있습니다. Domain이나 SSL 등이 이에 해당합니다.</p>
  285. <ul>
  286. <li><strong>Alternate Domain Names</strong>: Route53에 등록할 Domain을 적는다.<br />
  287. (단, Custom Domain을 사용하지 않고 *.cloudfront.net 도메인을 쓰려면 공란으로 놔둠)<br />
  288. (예제일 경우 sample.dramancompany.com)</li>
  289. <li><strong>SSL Certificate</strong>: Custom SSL Certificate<br />
  290. (도메인에 맞는 인증서를 선택, 예제일 경우 *.dramancompany.com.)<br />
  291. (단, Custom Domain을 사용하지 않고 *.cloudfront.net 도메인을 쓰려면 Default 선택)<br />
  292. (SSL 인증서는 us-east-1 region에 존재해야 사용할 수 있다)</li>
  293. <li><span data-token-index="4" data-reactroot=""><strong>Default Root Object</strong>: </span>index.html<br />
  294. (sample.dramncompany.com/ 으로 request가 들어오면 sample.dramncompany.com/index.html로 request를 바꾸어줌)</li>
  295. </ul>
  296. <h3>Distribution 생성 마무리</h3>
  297. <p>모든 설정을 완료했다면 마지막으로 생성 버튼을 눌러 Distribution을 생성해야 합니다. 생성하고 나면 <strong>InProgress</strong> 상태의 Distribution을 확인 할 수 있는데 모든 작업이 완료되고 <strong>Deployed</strong> 상태가 되는 데까지 약 20분의 시간이 걸립니다.</p>
  298. <p>Deployed 상태가 되었다면 <span style="font-family: monospace;">*.cloudfront.net</span>과 같은 pattern의 Domain이 주어지는데 이를 통해 웹에 접근 할 수 있습니다.</p>
  299. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?ssl=1"><img data-attachment-id="1107" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-7-55-17/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?fit=2994%2C1576&amp;ssl=1" data-orig-size="2994,1576" 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="스크린샷 2019-09-02 오후 7.55.17" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?resize=449%2C304&amp;ssl=1" class="aligncenter wp-image-1107" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?resize=646%2C340&#038;ssl=1" alt="" width="646" height="340" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?w=2994&amp;ssl=1 2994w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?resize=768%2C404&amp;ssl=1 768w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.55.17.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 646px) 100vw, 646px" data-recalc-dims="1" /></a></p>
  300. <p>지금처럼 각자 S3에 업로드 해놓은 page가 뜬다면 성공입니다.</p>
  301. <h2>4. 생성된 Distribution에 Error pages 설정 추가하기</h2>
  302. <p>지금까지 S3 Bucket을 생성하고 Cloudfront에 S3를 연결하여 웹페이지를 배포하는 것까지 진행하였습니다.</p>
  303. <p>하지만 아직 끝난 게 아닙니다. 우리가 개발하고 있는 Web App들에는 Route마다 보여야 하는 페이지가 다를 수 있습니다. 만약 예를 들어 /test라는 route가 존재한다고 하면 현재 상태에서 해당 route로 접근 시 에러가 발생하게 됩니다. 내가 react-router-dom 등을 이용하여 앱 내부적으로 Route를 나누었어도 실제론 제대로 동작하지 않습니다.</p>
  304. <p><div id="attachment_1109" style="width: 3006px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?ssl=1"><img aria-describedby="caption-attachment-1109" data-attachment-id="1109" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-8-01-12/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?fit=2996%2C1578&amp;ssl=1" data-orig-size="2996,1578" 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="스크린샷 2019-09-02 오후 8.01.12" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?resize=449%2C304&amp;ssl=1" class="size-full wp-image-1109" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?resize=1170%2C616&#038;ssl=1" alt="" width="1170" height="616" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?w=2996&amp;ssl=1 2996w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?resize=768%2C405&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.01.12.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a><p id="caption-attachment-1109" class="wp-caption-text">/test로 접근시 에러가 나는 모습</p></div></p>
  305. <p>그 이유는 바로 Cloudfront가 test라는 File을 찾아 유저에게 전달하려고 하기 때문입니다. cloudfront는 단순히 S3의 Object들을 유저에게 가장 가까운 Edge에 Caching 해두어 요청이 왔을 때 보다 빠르게 Object를 전달해주기 위해 만들어진 서비스이기 때문이죠.</p>
  306. <p>즉 우리는 에러가 났을 때도 index.html로 접근 할 수 있도록 설정해 주어야 합니다.</p>
  307. <p>이러한 설정은 어떻게 할 수 있을까요? 바로 Error pages 설정을 가지고 해결 할 수 있습니다.</p>
  308. <p>서버에 정해진 File이 존재하지 않을 때 발생하는 Error인 <strong>403 Forbidden</strong>의 response로 index.html을 대신 전달하게 하면 문제를 해결 할 수 있습니다.</p>
  309. <h3>Error Pages</h3>
  310. <p>우리가 만들어놓은 Distribution의 Dash Board에 진입하면 상단에 Error Pages라는 Tab을 볼 수 있습니다.</p>
  311. <p><div id="attachment_1110" style="width: 2594px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?ssl=1"><img aria-describedby="caption-attachment-1110" data-attachment-id="1110" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-8-07-06/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?fit=2584%2C570&amp;ssl=1" data-orig-size="2584,570" 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="스크린샷 2019-09-02 오후 8.07.06" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?resize=449%2C304&amp;ssl=1" class="size-full wp-image-1110" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?resize=1170%2C258&#038;ssl=1" alt="" width="1170" height="258" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?w=2584&amp;ssl=1 2584w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?resize=768%2C169&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.07.06.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a><p id="caption-attachment-1110" class="wp-caption-text">Error Pages 탭</p></div></p>
  312. <p>Create Custom Error Response를 클릭하여</p>
  313. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?ssl=1"><img data-attachment-id="1111" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-8-08-25/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?fit=1464%2C742&amp;ssl=1" data-orig-size="1464,742" 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="스크린샷 2019-09-02 오후 8.08.25" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?resize=449%2C304&amp;ssl=1" class="aligncenter size-full wp-image-1111" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?resize=1170%2C593&#038;ssl=1" alt="" width="1170" height="593" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?w=1464&amp;ssl=1 1464w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.08.25.png?resize=768%2C389&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  314. <p>다음과 같이 설정 후에 Create를 눌러줍니다. 반영되는 시간이 조금 걸리니 일정 시간이 흐른 후 /test에 다시 접근해 보도록 합시다.</p>
  315. <p><div id="attachment_1112" style="width: 656px" class="wp-caption aligncenter"><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?ssl=1"><img aria-describedby="caption-attachment-1112" data-attachment-id="1112" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-8-17-02/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?fit=2540%2C1656&amp;ssl=1" data-orig-size="2540,1656" 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="스크린샷 2019-09-02 오후 8.17.02" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?resize=449%2C304&amp;ssl=1" class="wp-image-1112" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?resize=646%2C421&#038;ssl=1" alt="" width="646" height="421" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?w=2540&amp;ssl=1 2540w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?resize=768%2C501&amp;ssl=1 768w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.17.02.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 646px) 100vw, 646px" data-recalc-dims="1" /></a><p id="caption-attachment-1112" class="wp-caption-text">/test path에 제대로 접근 된 모습</p></div></p>
  316. <p>설정 후 Error가 뜨지 않고 제대로 Rendering 되는 모습을 볼 수 있습니다.</p>
  317. <h2>5. Route53에 CloudFront Domain 설정하기</h2>
  318. <p>이제 거의 막바지 작업입니다. 우리는 CloudFront Default Domain으로 서비스를 할 것이 아니기 때문에 Route53에서 우리가 만든 Domain Record와 CloudFront의 Default Domain을 연결해줘야 합니다.</p>
  319. <p>일단 AWS의 Route53 Dashboard에 접근하여 위에 CloudFront 생성 시 등록했던 Domain의 호스팅 영역을 생성 혹은 Dashboard에 진입합니다. (예제일 경우 dramancompany.com)</p>
  320. <p>진입 후에는 레코드 세트 생성 버튼을 클릭하여 다음과 같이 설정합니다.</p>
  321. <p>유형은 <strong>A &#8211; IPv4 주소</strong>, 별칭은 <strong>예</strong>를 선택하며 별칭 대상으로는 CloudFront의 Default domain으로 검색하면 CloudFront 배포 항목으로 자동 완성되며 선택 후 레코드 생성을 완료하면 됩니다.</p>
  322. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?ssl=1"><img data-attachment-id="1114" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-8-26-19/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?fit=812%2C980&amp;ssl=1" data-orig-size="812,980" 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="스크린샷 2019-09-02 오후 8.26.19" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?resize=449%2C304&amp;ssl=1" class="aligncenter wp-image-1114 " src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?resize=420%2C542&#038;ssl=1" alt="" width="420" height="542" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?zoom=2&amp;resize=420%2C542&amp;ssl=1 840w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-8.26.19.png?zoom=3&amp;resize=420%2C542&amp;ssl=1 1260w" sizes="(max-width: 420px) 100vw, 420px" data-recalc-dims="1" /></a></p>
  323. <p>Route53 설정까지 완료됐다면 해당 Domain으로 접근했을 때 성공적으로 Web이 뜨고 자물쇠 모양도 잘 보인다면 성공입니다!</p>
  324. <p><div id="attachment_1115" style="width: 656px" class="wp-caption aligncenter"><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?ssl=1"><img aria-describedby="caption-attachment-1115" data-attachment-id="1115" data-permalink="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/%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-2019-09-02-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-7-38-44/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?fit=1904%2C1572&amp;ssl=1" data-orig-size="1904,1572" 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="스크린샷 2019-09-02 오후 7.38.44" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?resize=449%2C304&amp;ssl=1" class="wp-image-1115" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?resize=646%2C533&#038;ssl=1" alt="" width="646" height="533" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?w=1904&amp;ssl=1 1904w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-02-오후-7.38.44.png?resize=768%2C634&amp;ssl=1 768w" sizes="(max-width: 646px) 100vw, 646px" data-recalc-dims="1" /></a><p id="caption-attachment-1115" class="wp-caption-text">성공적으로 Domain에 연결 된 모습</p></div></p>
  325. <h2>6. 간단한 배포 스크립트 만들기</h2>
  326. <p>지금까지 S3와 CloudFront 그리고 Route53을 통해서 웹을 배포해보았습니다. 하지만 배포는 한번 하고 끝나는 것이 아닌 개발이 완료될 때마다 해야 하는 반복 작업이기 때문에 배포를 쉽게 해주는 작업이 매우 중요합니다. 따라서 배포 스크립트를 작성해보도록 하겠습니다.</p>
  327. <ul>
  328. <li>기본적으로 아래의 script를 사용하려면 local에 aws cli 설정이 되어있어야 합니다.</li>
  329. </ul>
  330. <h3>build</h3>
  331. <p></p><pre class="crayon-plain-tag">"build": "react-scripts build"</pre><p></p>
  332. <ul>
  333. <li>create-react-app으로 project를 만들었다면 처음부터 만들어져 있는 Build script입니다.</li>
  334. <li>해당 스크립트를 실행하고 나면 Project의 Root에 build라는 폴더가 만들어집니다.</li>
  335. </ul>
  336. <h3>sync</h3>
  337. <p></p><pre class="crayon-plain-tag">"sync": "aws s3 sync ./build s3://S3-Bucket-Name --delete"</pre><p></p>
  338. <ul>
  339. <li>S3 bucket에 local에 있는 build 폴더를 sync 합니다.</li>
  340. <li>스크립트에서 S3-Bucket-Name에는 각자의 Bucket Name을 적습니다 (예: s3://sample.dramancompany.com)</li>
  341. <li>delete option을 주어 이전 버전의 File들을 자동으로 삭제하도록 하여 불필요하게 S3 bucket의 용량이 늘어나는 것을 방지합니다.</li>
  342. </ul>
  343. <h3>invalidations</h3>
  344. <p></p><pre class="crayon-plain-tag">"invalidations": "aws cloudfront create-invalidation --distribution-id Distribution-ID --paths '/*'"</pre><p></p>
  345. <ul>
  346. <li>CloudFront는 유저의 요청을 기본 24시간 동안 Caching 해두기 때문에 캐시 무효화 작업을 해주지 않으면 유저는 이전 버전의 파일들을 CloudFront에 요청하게 됩니다.</li>
  347. <li>캐시 무효화 작업을 해주는 것을 invalidations라고 하며 스크립트에서 Distribution-ID에는 각자 생성한 Distribution의 ID 값을 넣어 사용합니다.</li>
  348. </ul>
  349. <h3>deploy</h3>
  350. <p></p><pre class="crayon-plain-tag">"deploy": "react-scripts build &amp;&amp; aws s3 sync ./build s3://S3-Bucket-Name --delete &amp;&amp; aws cloudfront create-invalidation --distribution-id Distribution-ID --paths '/*'",</pre><p></p>
  351. <ul>
  352. <li>build → sync → invalidations 작업을 순차적으로 진행합니다.</li>
  353. </ul>
  354. <h1>맺으며</h1>
  355. <p>이렇게 React​를 S3와 CloudFront 그리고 Route53을 이용해 서버 없이 배포하는 법에 대해 살펴보았는데요, 초기 서버 세팅 시간도 많이 들지 않고 간단하게 서비스를 배포할 수 있으면서, 비용적인 측면에서도 많은 장점이 있는 운영 방식인 것 같습니다.</p>
  356. <p>다음 포스트에서는 Github, CodePipeline, CodeBuild를 이용하여 자동 배포 시스템을 구축하고 [email protected]를 사용하여 Server Side Rendering을 하지 않고도 특정 page의 meta data를 다르게 해주는 SEO 방법에 대해 알아보도록 하겠습니다.</p>
  357. <p>그리고 글이 도움이 되셨다면 <a href="https://career.rememberapp.co.kr/talent">리멤버 커리어</a>를 한번 써보시는 것은 어떨까요? 나의 가치를 알아주는 회사가 더 높은 연봉과 함께 찾아올지도 모릅니다! <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br />
  358. 드라마앤컴퍼니 또한 언제나 문이 열려있으니 관심 있으시면 <a href="http://dramancompany.com/joinus/">지원</a>해보시는 것도 좋을 것 같습니다. 감사합니다.</p>
  359. <h1>참고 링크</h1>
  360. <ul>
  361. <li><a href="https://aws.amazon.com/ko/premiumsupport/knowledge-center/cloudfront-serve-static-website/">https://aws.amazon.com/ko/premiumsupport/knowledge-center/cloudfront-serve-static-website/</a></li>
  362. <li><a href="https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Introduction.html">https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Introduction.html</a></li>
  363. </ul>
  364. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/">AWS로 서버 없이 웹 서비스 운영하기 &#8211; 1</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  365. ]]></content:encoded>
  366. <wfw:commentRss>https://blog.dramancompany.com/2019/09/aws%eb%a1%9c-%ec%84%9c%eb%b2%84-%ec%97%86%ec%9d%b4-%ec%9b%b9-%ec%84%9c%eb%b9%84%ec%8a%a4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0-1/feed/</wfw:commentRss>
  367. <slash:comments>9</slash:comments>
  368. <post-id xmlns="com-wordpress:feed-additions:1">1081</post-id> </item>
  369. <item>
  370. <title>모바일 UI 테스트 자동화 구축하기</title>
  371. <link>https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/</link>
  372. <comments>https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/#comments</comments>
  373. <pubDate>Thu, 05 Sep 2019 03:06:29 +0000</pubDate>
  374. <dc:creator><![CDATA[sumin]]></dc:creator>
  375. <category><![CDATA[기술 블로그]]></category>
  376. <category><![CDATA[Appium]]></category>
  377. <category><![CDATA[Automation Test]]></category>
  378. <category><![CDATA[Mobile Test]]></category>
  379. <category><![CDATA[QA Test]]></category>
  380. <category><![CDATA[Test Automation]]></category>
  381. <category><![CDATA[UI Automation]]></category>
  382. <category><![CDATA[UI Test]]></category>
  383.  
  384. <guid isPermaLink="false">http://blog.dramancompany.com/?p=1078</guid>
  385. <description><![CDATA[<p>안녕하세요. 드라마앤컴퍼니의 곽수민입니다. 지난 포스팅에 이어서 모바일에서 UI 테스트 자동화를 실행하기 위한 Setting 방법과 실제 디바이스에 설치되어 있는 제품과의 연결을 시도해보려고 합니다. 개발환경 Setting 기본적으로 자동화 시스템을 구축하는 것도 실제 개발하는 것과 환경이 크게 차이가 없습니다. 제가 사용하고 있는 MAC OS 기준으로 환경정보를 구성하는 방법을 소개하겠습니다. OS : Mac 10.14 (최신버전) iOS &#8211; MAC OS<a class="button" href="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/" title="Read More">Read more</a></p>
  386. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/">모바일 UI 테스트 자동화 구축하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  387. ]]></description>
  388. <content:encoded><![CDATA[<p>안녕하세요. 드라마앤컴퍼니의 곽수민입니다.</p>
  389. <p>지난 포스팅에 이어서 모바일에서 UI 테스트 자동화를 실행하기 위한 Setting 방법과 실제 디바이스에 설치되어 있는 제품과의 연결을 시도해보려고 합니다.</p>
  390. <h3><strong>개발환경 Setting</strong></h3>
  391. <p>기본적으로 자동화 시스템을 구축하는 것도 실제 개발하는 것과 환경이 크게 차이가 없습니다. 제가 사용하고 있는 MAC OS 기준으로 환경정보를 구성하는 방법을 소개하겠습니다.</p>
  392. <table style="width: 98.5572%;">
  393. <tbody>
  394. <tr style="height: 152px;">
  395. <td style="width: 14.1935%; text-align: center; height: 311.438px;" rowspan="2">OS :<br />
  396. Mac 10.14 (최신버전)</td>
  397. <td style="width: 76.2903%; text-align: left; height: 152px;">iOS<br />
  398. &#8211; MAC OS 최신버전<br />
  399. &#8211; node.js (10.6) 최신버전<br />
  400. &#8211; Xcode 10.1 이상<br />
  401. &#8211; Apple Developer Tools (iOS simulator SDK&lt; command line tools)<br />
  402. * iOS Simulator 사용에 대한 인증 필요<br />
  403. &#8211; Apache Maven 설치 및 환경변수 Setting<br />
  404. &#8211; Appium Server (CUI/GUI)<br />
  405. * Appium에서 제공하는 ‘WebdriverAgent’ Remote Application</td>
  406. </tr>
  407. <tr style="height: 159.438px;">
  408. <td style="width: 76.2903%; height: 159.438px;">Android<br />
  409. &#8211; node.js (10.6) 최신버전<br />
  410. &#8211; Android SDK 및 환경변수 설정<br />
  411. &#8211; Android tool (API Level)<br />
  412. &#8211; JDK 설치 및 환경변수 Setting (JAVA, JAVAC)<br />
  413. &#8211; Apache Maven 설치 및 환경변수 Setting<br />
  414. &#8211; ADB (Android Debug Bridge)<br />
  415. &#8211; Appium Server (CUI/GUI)</td>
  416. </tr>
  417. </tbody>
  418. </table>
  419. <p>* 필수 : Apple의 Developer 계정(개인 계정도 관계 없음)을 생성해두어야 합니다. Xcode Build 옵션 중 Test 모드에서 WebdriverAgent 을 실제 기기에 빌드할 때 올바른 서명을 포함해야 하기 때문입니다.</p>
  420. <p>위 도구들의 셋팅 방법은 구글링이나 포털 검색을 통해서 차근차근 진행해보시기 바랍니다.</p>
  421. <h3><strong>Appium (자동화 도구)</strong></h3>
  422. <p>세상에는 여러가지 자동화 도구들이 있습니다.</p>
  423. <p>그 중에서도 저희가 Appium을 이용하여 자동화를 구축한 이유는 다음과 같습니다.</p>
  424. <ol>
  425. <li>iOS / Android 모두 지원</li>
  426. <li>다양한 Scripting 언어를 지원 (JAVA, Python, Ruby, C# 등&#8230;)</li>
  427. <li>Multi-Testing</li>
  428. </ol>
  429. <p>Appium 서버는 개발자가 테스트 프레임워크에서 제공하는 API(WebDriver JSON Wire Protocol)를 사용한 다양한 언어 베이스의 스크립트를 HTTP Commands로 받아주고 스크립트 상의 명령어들을 디바이스에 전송하여 실행하고, 그 결과를 받아와서 Console에 기록해줍니다.</p>
  430. <p>우리가 원하는 모바일의 대표적인 OS를 모두 지원하였고, 다양한 스크립트 언어로 본인이 원하는 방식의 스크립트를 짤 수 있었던게 가장 큰 핵심이었습니다. 또한, 안드로이드의 경우 여러가지 앱을 ADB(Android Debug Bridge)로 병렬 연결하여 한번에 여러 디바이스의 테스트도 가능합니다. (안드로이드는 보통 환경적인 이슈도 많다보니, QA검수 때 iOS보다 환경 선택의 커버리지가 넓은 편이기 때문에 여러 디바이스를 동시에 테스트 할 수 있는 부분이 매력적이었습니다.)</p>
  431. <p>하지만 단점으로는 오픈소스 라이센스의 특성 상 여러가지 문제 (1. 진입 장벽이 높다. 2. Customer Service의 장벽 3. 구글링을 통한 내용들이 잘못된 정보일수도 있다.) 들이 존재하기도 합니다.</p>
  432. <p style="text-align: center;"><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?ssl=1"><img data-attachment-id="1128" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-03-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-19-08/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?fit=958%2C488&amp;ssl=1" data-orig-size="958,488" 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="스크린샷 2019-09-03 오후 5.19.08" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-1128" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?resize=958%2C488&#038;ssl=1" alt="" width="958" height="488" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?w=958&amp;ssl=1 958w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-03-오후-5.19.08.png?resize=768%2C391&amp;ssl=1 768w" sizes="(max-width: 958px) 100vw, 958px" data-recalc-dims="1" /></a></p>
  433. <p style="text-align: right;">          출처 : appium.io</p>
  434. <p>국내에는 UI 테스트 자동화 관련 서적은 있지만 초보자가 책을 다뤄보기에는 큰 진입장벽이 있고, 더불어 프로그래밍 지식이 없다면 정보가 매우 제한적일 수 있습니다. 하지만 이 포스팅으로 많은 분들이 더 나은 환경을 구축해보셨으면 좋겠습니다.</p>
  435. <p style="text-align: center;"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.51.24.png?ssl=1"><img data-attachment-id="1196" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-05-%e1%84%8b%e1%85%a9%e1%84%8c%e1%85%a5%e1%86%ab-11-51-24/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.51.24.png?fit=389%2C104&amp;ssl=1" data-orig-size="389,104" 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="스크린샷 2019-09-05 오전 11.51.24" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.51.24.png?resize=290%2C104&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.51.24.png?resize=389%2C104&amp;ssl=1" class="alignnone size-full wp-image-1196" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.51.24.png?resize=389%2C104&#038;ssl=1" alt="" width="389" height="104" data-recalc-dims="1" /></a></p>
  436. <p style="text-align: right;">출처 : appium.io</p>
  437. <p>Appium GUI에서는 모바일 화면의 <strong>모든 Element</strong>에 대해서 개발에 필요한 기본 초석이 되는 리소스들을 사용자에게 제공해줍니다. (아래는 간략한 방법입니다.)</p>
  438. <p>우선 디바이스와 Appium을 연결해주어야 합니다. 위에서 설명드린 것처럼 iOS는 WebDriverAgent라는 Remote앱을 미리 Xcode에서<strong> Test모드로 빌드</strong>한 상태여야 합니다. (이 부분은 내용이 매우 복잡한 관계로 추후에 다루겠습니다.) Android OS는 &#8216;USB 디버깅&#8217; 모드가 활성화 되고 ADB를 통하여 PC와 연결된 후에 아래 내용을 진행할 수 있습니다.<br />
  439. <strong><em>(*참고로 USB 디버깅 모드를 활성화 시키려면 휴대폰의 설정&gt; 휴대전화 정보&gt; 소프트웨어 정보&gt; &#8216;빌드번호&#8217; 내역을 여러번 터치하면 개발자 모드를 활성화 시킬 수 있고, 다시 휴대폰의 설정&gt;개발자 옵션을 통하여 &#8216;USB 디버깅&#8217; 모드를 활성화 시킬 수 있습니다.)</em></strong></p>
  440. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?ssl=1"><img data-attachment-id="1166" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-04-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-31-00-2/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?fit=1280%2C1188&amp;ssl=1" data-orig-size="1280,1188" 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="스크린샷 2019-09-04 오후 5.31.00" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1166 aligncenter" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?resize=657%2C610&#038;ssl=1" alt="" width="657" height="610" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?w=1280&amp;ssl=1 1280w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.00-1.png?resize=768%2C713&amp;ssl=1 768w" sizes="(max-width: 657px) 100vw, 657px" data-recalc-dims="1" /></a></p>
  441. <p>Appium의 처음 실행화면입니다. Host와 Port를 직접 구성하여 쓸 수 있는데, 동일한 Host를 구성하여 Appium을 열어주었다면 실행이 불가능해질 수 있으므로 잘 체크하도록 합시다.</p>
  442. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?ssl=1"><img data-attachment-id="1170" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-04-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-31-06-3/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?fit=1294%2C1182&amp;ssl=1" data-orig-size="1294,1182" 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="스크린샷 2019-09-04 오후 5.31.06" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1170 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?resize=657%2C600&#038;ssl=1" alt="" width="657" height="600" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?w=1294&amp;ssl=1 1294w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.31.06-2.png?resize=768%2C702&amp;ssl=1 768w" sizes="(max-width: 657px) 100vw, 657px" data-recalc-dims="1" /></a></p>
  443. <p>Appium이 정상적으로 실행된 모습입니다. 상단 &#8216;돋보기&#8217; 모양의 버튼을 눌러 Starter inspector Session 설정창을 띄워줍니다.</p>
  444. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?ssl=1"><img data-attachment-id="1168" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-04-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-32-06-2/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?fit=2140%2C1410&amp;ssl=1" data-orig-size="2140,1410" 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="스크린샷 2019-09-04 오후 5.32.06" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1168 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?resize=832%2C548&#038;ssl=1" alt="" width="832" height="548" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?w=2140&amp;ssl=1 2140w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.32.06-1.png?resize=768%2C506&amp;ssl=1 768w" sizes="(max-width: 832px) 100vw, 832px" data-recalc-dims="1" /></a></p>
  445. <p>Inspector Session에서 Custom Server탭으로 구성하여 서버를 초기에 생성한 Host와 Port란을 채워줍니다.</p>
  446. <p>디바이스와의 연결을 위하여 이미지를 참고해서 platformName, PlatforVersion, BundleID(실행해야 할 어플리케이션), automationName, udid, deviceName등을 위의 예시처럼 기입해줍시다.</p>
  447. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?ssl=1"><img data-attachment-id="1169" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-04-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-36-40-2/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?fit=3336%2C2074&amp;ssl=1" data-orig-size="3336,2074" 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="스크린샷 2019-09-04 오후 5.36.40" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1169 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?resize=973%2C605&#038;ssl=1" alt="" width="973" height="605" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?w=3336&amp;ssl=1 3336w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?resize=768%2C477&amp;ssl=1 768w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-04-오후-5.36.40-1.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 973px) 100vw, 973px" data-recalc-dims="1" /></a></p>
  448. <p>연결이 정상적으로 완료되었다면 다음과 같은 화면이 나타나고, 우리가 해야할 자동화 스크립트 생산에 필요한 정보들을 습득할 수 있습니다. 보통 iOS 기준으로는 accessibility id, name주로 쓰게 되는데, 때로는 xpath값을 쓰기도 합니다. (xpath의 치명적인 단점으로 왠만하면 모든 &#8216;Element&#8217;들을 쉽게 다룰 수 있지만, 검색속도가 느려 전체적인 자동화 속도에 크게 영향을 미칩니다.) 어디에, 어떻게 해당 Element를 적절하게 활용해야 하는지는 추후 자동화 스크립트를 본격적으로 개발하면서 설명드리겠습니다.</p>
  449. <h3><strong>자동화 스크립트를 개발하기전에!</strong></h3>
  450. <p>자동화 스크립트를 개발하기 위해서는 우선 Eclipse에서 Maven Project 를 생성하고 <strong>pom.xml 파일에 자동화 개발 관련 Appium과의 Dependency를 설정</strong>해주어야 합니다. (해당 글에서는 Eclipse 도구를 이용하여 진행하겠습니다.)</p>
  451. <p>먼저 설치한 Eclipse를 실행합니다.</p>
  452. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?ssl=1"><img data-attachment-id="1182" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/elipse-%e1%84%91%e1%85%b3%e1%84%85%e1%85%a9%e1%84%8c%e1%85%a6%e1%86%a8%e1%84%90%e1%85%b3-%e1%84%89%e1%85%a2%e1%86%bc%e1%84%89%e1%85%a5%e1%86%bc-%e1%84%92%e1%85%aa%e1%84%86%e1%85%a7%e1%86%ab/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?fit=2094%2C1418&amp;ssl=1" data-orig-size="2094,1418" 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="Elipse 프로젝트 생성 화면" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1182 aligncenter" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?resize=781%2C529&#038;ssl=1" alt="" width="781" height="529" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?w=2094&amp;ssl=1 2094w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?resize=768%2C520&amp;ssl=1 768w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/Elipse-프로젝트-생성-화면.png?resize=449%2C304&amp;ssl=1 449w" sizes="(max-width: 781px) 100vw, 781px" data-recalc-dims="1" /></a></p>
  453. <p>해당 화면에서 [File] &gt; [New] &gt; [Maven Project] 메뉴를 선택해 줍니다.</p>
  454. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?ssl=1"><img data-attachment-id="1180" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-05-%e1%84%8b%e1%85%a9%e1%84%8c%e1%85%a5%e1%86%ab-10-24-12/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?fit=1236%2C1050&amp;ssl=1" data-orig-size="1236,1050" 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="스크린샷 2019-09-05 오전 10.24.12" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1180 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?resize=746%2C634&#038;ssl=1" alt="" width="746" height="634" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?w=1236&amp;ssl=1 1236w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-10.24.12.png?resize=768%2C652&amp;ssl=1 768w" sizes="(max-width: 746px) 100vw, 746px" data-recalc-dims="1" /></a></p>
  455. <p>New Maven Project창에서 Next를 누르다가 해당 화면이 나오면 Group ID, artifact Id를 입력하고 [Finish] 버튼을 눌러줍시다.</p>
  456. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?ssl=1"><img data-attachment-id="1183" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-05-%e1%84%8b%e1%85%a9%e1%84%8c%e1%85%a5%e1%86%ab-11-01-40/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?fit=1826%2C1280&amp;ssl=1" data-orig-size="1826,1280" 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="스크린샷 2019-09-05 오전 11.01.40" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1183 aligncenter" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?resize=781%2C548&#038;ssl=1" alt="" width="781" height="548" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?w=1826&amp;ssl=1 1826w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.01.40.png?resize=768%2C538&amp;ssl=1 768w" sizes="(max-width: 781px) 100vw, 781px" data-recalc-dims="1" /></a></p>
  457. <p>메이븐 프로젝트가 정상적으로 생성되었으면, Pakage Explorer영역에서 pom.xml 파일을 접근한 뒤, Selenium, TestNG, junit, Appium Java Client 과의 Dependency 를 이미지와 같이 설정해줍니다. 이렇게 하면 자동화를 위한 기본 Setting은 모두 완료되었습니다.</p>
  458. <h3><strong>자동화 스크립트</strong></h3>
  459. <p>자동화는 반복되는 작업들을 &#8216;자동화&#8217; 함으로써 리소스 확보는 물론 제품의 갯수가 늘고 앱의 기능이 추가/변경되어 전체적인 볼륨이 커지는 상황에서도 빛을 발할 수 있습니다. 또한, 이전 포스팅에서도 언급했듯이 컴퓨터는 짜여진 코드 구성으로 반복적인 일을 하게 됨으로써 <strong>일관성 있는 테스트 결과를 받아볼 수 있는데 큰 장점</strong>이 있습니다.</p>
  460. <p>저희는 Eclipse 또는 Visual Studio Code 도구를 이용하여 Selenium Library에 기반한 자동화 관련 소스를 생산해내고 있습니다. 실제 테스트는 코딩 도구의 MarketPlace에서 활용할 수 있는 Extensions 중 <strong>Java Test Runner</strong>라는 Extension을 활용하여 테스트 기기나 가상 머신을 제어할 수 있도록 구성하였습니다.</p>
  461. <p>우선, 생성된 프로젝트 내에 있는 src/test/java 경로 하위에 클래스를 생성해 줍니다.</p>
  462. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?ssl=1"><img data-attachment-id="1186" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-05-%e1%84%8b%e1%85%a9%e1%84%8c%e1%85%a5%e1%86%ab-11-20-38/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?fit=1290%2C320&amp;ssl=1" data-orig-size="1290,320" 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="스크린샷 2019-09-05 오전 11.20.38" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1186 aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?resize=1020%2C253&#038;ssl=1" alt="" width="1020" height="253" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?w=1290&amp;ssl=1 1290w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.20.38.png?resize=768%2C191&amp;ssl=1 768w" sizes="(max-width: 1020px) 100vw, 1020px" data-recalc-dims="1" /></a></p>
  463. <p>이렇게 생성된 클래스에서 실제 개발을 진행하게 되는데, 해당 바디는 크게 <strong>선처리, 후처리, 테스트 동작 메소드를</strong> 구성하게 됩니다. (해당 포스팅에서는 &#8216;선처리&#8217; 부분까지만 다루겠습니다.)</p>
  464. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?ssl=1"><img data-attachment-id="1187" data-permalink="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%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-2019-09-05-%e1%84%8b%e1%85%a9%e1%84%8c%e1%85%a5%e1%86%ab-11-25-52/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?fit=1580%2C728&amp;ssl=1" data-orig-size="1580,728" 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="스크린샷 2019-09-05 오전 11.25.52" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1187 aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?resize=805%2C371&#038;ssl=1" alt="" width="805" height="371" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?w=1580&amp;ssl=1 1580w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/09/스크린샷-2019-09-05-오전-11.25.52.png?resize=768%2C354&amp;ssl=1 768w" sizes="(max-width: 805px) 100vw, 805px" data-recalc-dims="1" /></a></p>
  465. <p><strong>선처리</strong>는 기본 개발환경을 세팅하고, appium과의 연결을 처리해주는 부분으로 이해할 수 있습니다. 기본적으로 디바이스 이름/버전 , 플랫폼 이름/버전, Product의 Bundle ID, 기기 고유번호, RemoteUrl(appium local host, port)등이 포함됩니다.</p>
  466. <p>참고로 각 모바일 환경마다 선처리(환경정보 세팅) 방법에 대한 코드 예제는 아래와 같습니다.</p><pre class="crayon-plain-tag">@BeforeSuite //iOS Device
  467. public void Setting() throws Exception
  468. {
  469.        DesiredCapabilities capabilities = new DesiredCapabilities();
  470.      
  471.         capabilities.setCapability("automationName", "{XCUITest}");
  472.         capabilities.setCapability("platformName", "{iOS}"); // 환경
  473.         capabilities.setCapability("deviceName", "{디바이스 이름}"); // 디바이스 이름
  474.         capabilities.setCapability("platformVersion", "{12.0.1}"); // OS 버전
  475.         capabilities.setCapability("bundleId", "{앱 패키지 네임}"); //앱 패키지 네임
  476.         capabilities.setCapability("udid", "{Device UDID}"); // 디바이스 고유 UDID (iOS)
  477.         capabilities.setCapability("noReset", true); // 테스트전에 리셋할건지 여부(true/false)
  478.  
  479.         URL remoteUrl = new URL("http://0.0.0.0:4723/wd/hub"); //WebDriver Hub ip/port (앱피움에서 확인)
  480.         wd = new IOSDriver(remoteUrl, capabilities);
  481. }</pre><p></p>
  482. <p style="text-align: center;"><strong>-iOS 선처리 예제-</strong></p>
  483. <p></p><pre class="crayon-plain-tag">@BeforeSuite //Android Device
  484. public void Setting() throws Exception
  485. {
  486.  
  487.        DesiredCapabilities capabilities = new DesiredCapabilities();
  488.    
  489.        capabilities.setCapability("appium-version", "{1.12.1}"); //UI Automator  사용하기 위함
  490.        capabilities.setCapability("automationName", "{uiautomator2}"); //Android 8.0 이상 필수
  491.        capabilities.setCapability("platformName", "{Android}");
  492.        capabilities.setCapability("platformVersion", "{9}");
  493.        capabilities.setCapability("deviceName", "{디바이스 이름}");
  494.        capabilities.setCapability("appPackage", "{앱 패키지 name}");
  495.        capabilities.setCapability("appActivity", "{스플래시 Activity name}");
  496.        capabilities.setCapability("noReset", true);
  497.        capabilities.setCapability("unicodeKeyboard", true); //appium 전용 keyboard 이용하기 위함
  498.        
  499.        URL remoteUrl = new URL("http://0.0.0.0:7273/wd/hub"); //WebDriver Hub ip/port (앱피움에서 확인)
  500.        wd = new AndroidDriver(remoteUrl, capabilities);
  501. }</pre><p></p>
  502. <p style="text-align: center;"><strong>-Android 선처리 예제-</strong></p>
  503. <p style="text-align: left;">위와 같이 각 환경정보에 필요한 내용들을 먼저 체크한 뒤 이후의 후처리 및 테스트 코드가 정상적으로 수행됩니다.</p>
  504. <h3>맺으며</h3>
  505. <p>저희는 직접 프로그래밍 기초 지식을 쌓는 동시에 수 만번의 시행착오를 겪으며 점진적으로 테스트 자동화 시스템을 구축 하였습니다. 그 결과 전체적인 QA팀 리소스 활용과 실제 검수 업무에도 큰 도움이 되었고, 사내 DTT(Drama Tech Talk)에도 소개할만큼 많은 분들께서 관심을 가져주시고 계십니다. 이 글을 쓰는 이유도 &#8216;많은 QA 직무에 있으신 분들이 테스트 자동화에 대한 관심을 가지고 더 나은 업무 프로세스를 만들 수 있도록 도움을 드릴 수 있겠다.&#8217; 였습니다.</p>
  506. <p>아직 포스팅으로 설명해야 할 부분들이 매우 많이 남았지만, 개발 환경 세팅을 하고 Appium과 실제 디바이스를 연결한 것만으로도 크게 한걸음 나아갔다고 해도 과언이 아닐 것 입니다.</p>
  507. <p>다음화는 iOS에서 가장 중요한 &#8216;<strong>WebDriverAgent Test모드로 빌드하기&#8217;</strong> 로 찾아 뵙겠습니다. 긴 글 읽어주셔서 감사합니다.</p>
  508. <p>P.S 잘 이해가지 않는 부분이 있다면 언제든, 어느분이든 댓글 남겨주세요.</p>
  509. <h3><strong>Appium 자동화 관련 참고링크</strong></h3>
  510. <ul>
  511. <li><a href="http://www.automationtestinghub.com/">http://www.automationtestinghub.com/</a></li>
  512. <li><a href="https://domich.wordpress.com/2016/01/11/appium-%ec%95%a0%ed%94%bc%ec%9b%80-%ed%94%84%eb%a1%9c%ed%8c%8c%ec%9d%bc%eb%a7%81-%ea%b8%b0%eb%b0%98-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%eb%8f%84%ea%b5%ac/">https://domich.wordpress.com/2016/01/11/appium-%ec%95%a0%ed%94%bc%ec%9b%80-%ed%94%84%eb%a1%9c%ed%8c%8c%ec%9d%bc%eb%a7%81-%ea%b8%b0%eb%b0%98-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%eb%8f%84%ea%b5%ac/</a></li>
  513. </ul>
  514. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/">모바일 UI 테스트 자동화 구축하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  515. ]]></content:encoded>
  516. <wfw:commentRss>https://blog.dramancompany.com/2019/09/%eb%aa%a8%eb%b0%94%ec%9d%bc-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ec%9e%90%eb%8f%99%ed%99%94-%ea%b5%ac%ec%b6%95%ed%95%98%ea%b8%b0/feed/</wfw:commentRss>
  517. <slash:comments>12</slash:comments>
  518. <post-id xmlns="com-wordpress:feed-additions:1">1078</post-id> </item>
  519. <item>
  520. <title>리멤버는 어떻게 명함을 정확히 인식할까? : OpenCV 이미지 프로세싱</title>
  521. <link>https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/</link>
  522. <comments>https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/#comments</comments>
  523. <pubDate>Thu, 21 Mar 2019 02:27:51 +0000</pubDate>
  524. <dc:creator><![CDATA[임 성민]]></dc:creator>
  525. <category><![CDATA[기술 블로그]]></category>
  526. <category><![CDATA[Android]]></category>
  527. <category><![CDATA[Camera]]></category>
  528. <category><![CDATA[Image Processing]]></category>
  529. <category><![CDATA[OpenCV]]></category>
  530.  
  531. <guid isPermaLink="false">http://blog.dramancompany.com/?p=1016</guid>
  532. <description><![CDATA[<p>리멤버 모바일 애플리케이션의 핵심 기능은 단연 카메라일 것입니다. 명함으로 연결되는 세상을 꿈꾸는 리멤버에게 카메라는 오프라인의 명함을 온라인상의 내 인맥으로 만드는 출발점이기 때문이죠. 그렇기 때문에 최대한 명함을 깔끔하게 인식하고, 깨끗하게 처리해서 타이피스트가 정확하게 입력할 수 있도록 전달하는 것이 리멤버 앱의 핵심 임무 중 하나입니다. 몇 년 전에 저희의 이러한 고민을 담아 블로그 글을 공개했었는데요, 새롭게 개발된 리멤버<a class="button" href="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/" title="Read More">Read more</a></p>
  533. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/">리멤버는 어떻게 명함을 정확히 인식할까? : OpenCV 이미지 프로세싱</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  534. ]]></description>
  535. <content:encoded><![CDATA[<p>리멤버 모바일 애플리케이션의 핵심 기능은 단연 카메라일 것입니다. 명함으로 연결되는 세상을 꿈꾸는 리멤버에게 카메라는 오프라인의 명함을 온라인상의 내 인맥으로 만드는 출발점이기 때문이죠. 그렇기 때문에 최대한 명함을 깔끔하게 인식하고, 깨끗하게 처리해서 타이피스트가 정확하게 입력할 수 있도록 전달하는 것이 리멤버 앱의 핵심 임무 중 하나입니다. 몇 년 전에 저희의 이러한 고민을 담아 <a class="external-link" href="https://blog.dramancompany.com/2016/04/crop/" rel="nofollow">블로그 글</a>을 공개했었는데요, 새롭게 개발된 리멤버 안드로이드 앱의 카메라 기능을 소개합니다.</p>
  536. <h3 id="OpenCV를이용한명함인식알고리즘개발-변한것들">새로운 카메라 엔진의 필요성</h3>
  537. <p>작년 5월, 리멤버가 대대적인 UI 개편을 하면서 카메라 UI 역시 크게 바뀌었습니다. 기존에는 아래와 같이 가로로 명함을 찍도록 유도하는 화면이었다면, 이제는 대부분의 카메라 앱과 마찬가지로 한손으로 편하게 휴대폰을 잡은 방향 그대로 촬영할 수 있도록 하는 것이죠. 하지만 지난 블로그에서 언급한 것처럼, 리멤버 안드로이드 앱에서는 개발의 용이성을 위해서 휴대폰 방향과 평행한 명함만 인식하게 되어있었습니다. 덕분에 많은 개발 리소스를 아낄 수 있었지만, 비스듬히 놓이거나, 휴대폰과 수직으로 놓인 명함은 전혀 인식하지 못했고, 이는 새로운 UI에서 매우 치명적인 허점이었습니다. 따라서 리멤버 리뉴얼을 위해서 새로운 카메라 엔진 개발은 필수적이었습니다.</p>
  538. <p><div id="attachment_1032" style="width: 580px" class="wp-caption aligncenter"><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_rememeber-e1553139108727.png?ssl=1"><img aria-describedby="caption-attachment-1032" data-attachment-id="1032" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_rememeber/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_rememeber.png?fit=1322%2C827&amp;ssl=1" data-orig-size="1322,827" 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="blog_rememeber" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_rememeber.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_rememeber.png?resize=1024%2C694&amp;ssl=1" class="wp-image-1032" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_rememeber.png?resize=570%2C356&#038;ssl=1" alt="" width="570" height="356" data-recalc-dims="1" /></a><p id="caption-attachment-1032" class="wp-caption-text">좌: 기존의 카메라 UI 우: 리뉴얼 후 카메라 UI</p></div></p>
  539. <p>또한, 리멤버 안드로이드 앱의 카메라 성능에 대한 피드백이 꾸준히 제기되고 있었습니다. 전반적으로는 괜찮은 성능을 보이지만, 미묘하게 가장자리가 제대로 인식되지 못하거나, 복잡한 배경 위에서는 명함을 제대로 인식하지 못하거나, 명함 촬영 가이드라인이 심하게 흔들리는 등 사용자의 촬영 경험에 좋지 않은 영향을 미치는 요소들이 매우 많았습니다. BoofCV 라이브러리의 한계와 레거시 코드의 영향으로 간단하고 사소한 개선이 불가능한 상태였고, 저희는 완전히 새로운 로직과 코드 위에서 카메라 엔진을 새롭게 만들기로 결심했습니다.</p>
  540. <h3 id="OpenCV를이용한명함인식알고리즘개발-그대로인것들"></h3>
  541. <h1 id="OpenCV를이용한명함인식알고리즘개발-명함인식알고리즘">명함 인식 알고리즘</h1>
  542. <p>저희의 1차적인 목표는 명함이 어떻게 배치되어 있든 명함을 인식할 수 있도록 하는 것이었습니다. 그러기 위해서는 기존에 사용하던 <a class="external-link" href="https://boofcv.org/index.php?title=Main_Page" rel="nofollow">BoofCV</a> 라이브러리를 포기해야 했습니다. 수직, 수평 방향 직선을 찾는 데에만 최적화되어 있고, Hough Transform을 제외한 모든 연산에서 좋지 않은 성능을 보였기 때문에 실시간 이미지 프로세싱에서 가장 방대한 레퍼런스를 제공하고 있는 <a class="external-link" href="https://opencv.org/" rel="nofollow">OpenCV</a>를 사용하기로 했습니다. 리멤버 앱의 명함 인식은 크게 아래와 같은 과정을 거칩니다.</p>
  543. <ol>
  544. <li>Pre-Processing</li>
  545. <li>Edge Detection</li>
  546. <li>Find Contours</li>
  547. <li>Find Rectangle</li>
  548. </ol>
  549. <h2 id="OpenCV를이용한명함인식알고리즘개발-Pre-Processing">Pre-Processing</h2>
  550. <p>리멤버 앱에서는 실시간으로 이미지를 처리하고, 사용자에게 명함의 위치를 보여줘야 했기 때문에 최대한 빠르게(100ms 이내) 이미지를 분석하고 그 안에서 명함을 찾아내야 했습니다. 하지만 요즘 스마트폰에서 보내주는 이미지는 해상도가 매우 높기 때문에 원본을 그대로 사용하면 이미지 처리에 매우 많은 시간이 걸립니다. 명함을 찾기 위해서 고화질의 이미지가 필요하지는 않으므로, 저희는 약 480px 수준으로 원본 이미지를 줄여서 사용했습니다.</p>
  551. <p>이미지를 줄인 후, 최대한 타겟으로 하는 명함 이미지가 두드러져 보이도록 여러 가지 전처리 작업을 해주었습니다. 저희는 명함과 뒷배경의 대비가 명확하고 uniform 한 경우는 물론이고, 명함과 비슷한 색의 배경, 또는 매우 지저분한 배경에서도 명함이 높은 확률로 인식될 수 있게 하고 싶었습니다. 특히 아래와 같은 상황들은 눈으로도 구분 짓기 어려운 경계선을 찾아내거나, 명확한 직선을 찾는 것을 방해하는 수많은 장애물을 최대한 걷어내야 했습니다.</p>
  552. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_original-e1553139395490.png?ssl=1"><img data-attachment-id="1033" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_original/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_original.png?fit=1500%2C531&amp;ssl=1" data-orig-size="1500,531" 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="blog_original" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_original.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_original.png?resize=784%2C531&amp;ssl=1" class="wp-image-1033 aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_original.png?resize=790%2C280&#038;ssl=1" alt="" width="790" height="280" data-recalc-dims="1" /></a></p>
  553. <p>따라서 자잘한 디테일은 숨기고, 큰 변화들이 두드러지는 데에 중점을 두고 이미지를 처리했습니다. 이를 위해서 먼저 OpenCV에서 제공하는 다양한 Image Blurring(Image Smoothing) 필터를 통해서 명함과 배경을 혼동하게 만드는 지저분한 정보들을 지운 뒤, Edge Preserving Filter를 통해 명함과 배경 사이의 흐려진 경계선을 최대한 복구했습니다. Edge Preserving Filter들은 이미지를 전반적으로는 부드럽게 만들지만, Edge라고 판단되는 곳, 즉 색상의 급격한 변화가 있는 곳은 더욱 뚜렷하게 만드는 효과가 있습니다.</p>
  554. <p>전처리를 거친 이미지는 아래와 같이 경계선을 판별하기 매우 좋은 상태로 다시 태어나게 됩니다.</p>
  555. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_preprocess.png?ssl=1"><img data-attachment-id="1034" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_preprocess/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_preprocess.png?fit=1500%2C531&amp;ssl=1" data-orig-size="1500,531" 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="blog_preprocess" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_preprocess.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_preprocess.png?resize=784%2C531&amp;ssl=1" class="wp-image-1034 aligncenter" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_preprocess.png?resize=790%2C280&#038;ssl=1" alt="" width="790" height="280" data-recalc-dims="1" /></a></p>
  556. <h2 id="OpenCV를이용한명함인식알고리즘개발-EdgeDetection">Edge Detection</h2>
  557. <p>이전보다 깔끔해진 이미지를 가지고 본격적으로 명함의 경계선을 찾아야 합니다. 이를 위해서 저희는 간단한게 OpenCV의 <a class="external-link" href="https://en.wikipedia.org/wiki/Canny_edge_detector" rel="nofollow">Canny Edge Detector</a>를 사용했습니다. Canny Edge Detector는 다섯 단계를 통해서 경계선을 추출해냅니다. 일반적인 사무실 책상에서 찍은 아래의 예시를 보겠습니다.</p>
  558. <p><div id="attachment_1039" style="width: 1837px" class="wp-caption aligncenter"><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_canny-1-e1553140028785.png?ssl=1"><img aria-describedby="caption-attachment-1039" data-attachment-id="1039" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_canny-1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_canny-1.png?fit=1827%2C443&amp;ssl=1" data-orig-size="1827,443" 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="blog_canny-1" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_canny-1.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_canny-1.png?resize=654%2C443&amp;ssl=1" class="size-full wp-image-1039" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_canny-1.png?resize=1170%2C284&#038;ssl=1" alt="" width="1170" height="284" data-recalc-dims="1" /></a><p id="caption-attachment-1039" class="wp-caption-text">왼쪽부터 원본, 전처리, Canny Edge Detection 결과</p></div></p>
  559. <p>위와 같이 전처리와 경계선 추출을 통해서 드디어 명함의 윤곽이 제대로 드러나기 시작했습니다! 이제 매우 간단하게 직사각형을 찾아낼 수 있을 것 같지만, 저희의 목적은 일반적인 사무실 책상 위의 하얀색 명함이 아니라, 그 어떤 명함과 배경에서도 성공적으로 명함을 찾아내는 것입니다. 따라서 한 가지 작업을 더 해주어야 했습니다. 다양한 배경에 명함이 위치하다보면, 명함의 경계선 중 일부분이 배경색과 같은 경우가 종종 있습니다. 이런 경우에는 Canny Edge Detector에서 찾아낸 Edge가 이어져있지 않고 끊어져있을 때도 있습니다. 사소한 균열일 수도 있지만, 매우 복잡한 배경 속에서 완벽하게 이어져있지 않은 직사각형은 종종 걸림돌이 되곤 했습니다. 따라서 저희는 <a class="external-link" href="https://en.wikipedia.org/wiki/Mathematical_morphology" rel="nofollow">Morphology 연산</a>을 통해서 최대한 균열을 메꾸고자 했습니다.</p>
  560. <p>Morphology 연산에는 주변의 가장 밝은 픽셀로 자신을 대체하는 팽창(Dilate)과, 가장 어두운 픽셀로 자신을 대체하는 침식(Erode) 연산이 있습니다. 팽창 연산을 하면 밝은 부분이 늘어나면서 서로 조금씩 떨어져 있던 파편들이 하나로 합쳐지게 되겠죠? 그리고 그 과정에서 하얀색이 차지하는 영역도 늘어나게 될 것입니다. 이 이미지에 침식 연산을 하면 영역은 원래의 크기대로 돌아가지만, 파편들은 여전히 붙어있게 됩니다. 결과적으로 영역의 크기는 유지하면서, 최대한 한 덩어리의 영역으로 합쳐진 이미지를 얻게 되는 것이죠. 아래의 그림을 보면 조금 이해가 되시나요?</p>
  561. <p><div id="attachment_1029" style="width: 910px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_whale-e1553137438937.png?ssl=1"><img aria-describedby="caption-attachment-1029" data-attachment-id="1029" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_whale/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_whale.png?fit=1849%2C416&amp;ssl=1" data-orig-size="1849,416" 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="blog_whale" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_whale.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_whale.png?resize=614%2C416&amp;ssl=1" class="wp-image-1029" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_whale.png?resize=900%2C202&#038;ssl=1" alt="" width="900" height="202" data-recalc-dims="1" /></a><p id="caption-attachment-1029" class="wp-caption-text">왼쪽부터 원본, 팽창 연산 후, 침식 연산 후.</p></div></p>
  562. <p>이처럼 팽창 후 침식 연산을 하는 것을 닫기(Close) 연산이라고 부릅니다. 이 닫기 연산을 통해서 Canny Edge Detection을 거친 뒤의 이미지의 균열을 보정했습니다.</p>
  563. <h2 id="OpenCV를이용한명함인식알고리즘개발-FindContours">Find Contours</h2>
  564. <p>Contour, 혹은 윤곽선은 같은 색을 가지는 모든 연속적인 점들을 둘러싼 곡선이라고 할 수 있습니다. 이전 Edge Detection에서 찾은 명함은 정확히 직사각형도 아닐 것이고, 주변의 수많은 방해물들로 둘러싸여 있을 테니, 일단 이들을 포괄하는 윤곽선들을 찾는 것입니다. 이렇게 찾은 윤곽선의 면적이 원본 이미지의 10% 이상을 차지하면, 이 윤곽선은 저희가 찾는 명함일 가능성이 있다고 판단하고 새로운 캔버스에 그려 넣습니다. 이렇게 작거나 쓸모없는 윤곽선을 쳐내고 나면, 명함 내부의 글씨나 책상 위의 무늬들은 사라지고 명함 자체의 윤곽선만 남게 됩니다.</p>
  565. <p><div id="attachment_1042" style="width: 765px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_edge_1-e1553140319764.png?ssl=1"><img aria-describedby="caption-attachment-1042" data-attachment-id="1042" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_edge_1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_edge_1.png?fit=1483%2C529&amp;ssl=1" data-orig-size="1483,529" 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="blog_edge_1" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_edge_1.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_edge_1.png?resize=781%2C529&amp;ssl=1" class="wp-image-1042" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_edge_1.png?resize=755%2C269&#038;ssl=1" alt="" width="755" height="269" data-recalc-dims="1" /></a><p id="caption-attachment-1042" class="wp-caption-text">좌: Edge Detection 후 우: 이미지에서 찾아진 Contours</p></div></p>
  566. <p>이미지 처리는 이 단계로 끝입니다. 이제 정말로 직선과 직사각형을 찾으러 가봅시다!</p>
  567. <h2 id="OpenCV를이용한명함인식알고리즘개발-FindRectangle">Find Rectangle</h2>
  568. <p>가장 먼저 <a class="external-link" href="https://en.wikipedia.org/wiki/Hough_transform" rel="nofollow">Hough Transform</a>을 이용해 이미지에서 직선을 찾습니다. 하지만 아무리 깔끔하게 윤곽선을 만들어 냈더라도, 아직 이미지에 남아있는 약간의 노이즈와 이미지 축소의 영향으로 완벽한 직선이 만들어지지 않을 수도 있습니다. 그 중 가장 대표적인 케이스는 끊어진 직선입니다. 따라서 저희는 만들어진 직선을 순회하면서 다음과 같은 조건을 찾습니다.</p>
  569. <ul>
  570. <li>평행한 두 직선</li>
  571. <li>한 끝점이 다른 직선과 매우 가까이 붙어있는 직선</li>
  572. </ul>
  573. <p>위 두 조건이 만족하면, 두 직선은 하나의 직선으로 간주하고 병합했습니다. 좀 더 배경이 복잡한 예시 이미지를 들고 와봤습니다. 아래 이미지를 전처리한 후 Hough Transform을 통해 직선을 찾아보니, 처음에는 왼쪽과 같이 14개의 직선이 발견되었습니다. 하지만 위와 같은 조건에 맞는 직선들을 찾아보니, 명함의 윗변과 아랫변을 이루는 각각 세 개의 직선들이 하나로 합쳐진 것을 볼 수 있습니다. 오른쪽 변에서도 직선 두 개가 합쳐져서, 이제 9개의 직선만 남게 되었습니다.</p>
  574. <p><div id="attachment_1043" style="width: 853px" class="wp-caption aligncenter"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_lines-e1553152046565.png?ssl=1"><img aria-describedby="caption-attachment-1043" data-attachment-id="1043" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_lines/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_lines.png?fit=1485%2C525&amp;ssl=1" data-orig-size="1485,525" 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="blog_lines" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_lines.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_lines.png?resize=775%2C525&amp;ssl=1" class="wp-image-1043" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_lines.png?resize=843%2C298&#038;ssl=1" alt="" width="843" height="298" data-recalc-dims="1" /></a><p id="caption-attachment-1043" class="wp-caption-text">좌: Hough Transform으로 찾은 직선들 우: 병합 후 남은 직선들</p></div></p>
  575. <p>이렇게 찾은 직선들을 가지고 직사각형을 만들어나가는데요, 사실상 직선들의 모든 조합을 가지고 가장 직사각형스러운 조합을 찾는 과정입니다. 하지만 꼭 모든 조합을 테스트해볼 필요는 없었습니다. 일단 직선 하나를 기준으로 본다면, 자신과 평행한 직선들과 수직인 직선들을 찾을 수 있겠죠. 평행한 직선들은 직사각형에서 자신과 마주 보는 변이라고 가정하고, 수직인 직선들은 자신과 인접한 변이라고 생각한다면 이 직선들 간의 관계를 규정할 수 있을 겁니다. 아래는 명함의 윗변을 기준으로 평행인 직선과 수직인 직선을 찾은 예시입니다.</p>
  576. <p><div id="attachment_1045" style="width: 847px" class="wp-caption aligncenter"><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_parallel-e1553153707691.png?ssl=1"><img aria-describedby="caption-attachment-1045" data-attachment-id="1045" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_parallel/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_parallel.png?fit=1493%2C525&amp;ssl=1" data-orig-size="1493,525" 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="blog_parallel" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_parallel.png?resize=300%2C228&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_parallel.png?resize=775%2C525&amp;ssl=1" class="wp-image-1045" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_parallel.png?resize=837%2C294&#038;ssl=1" alt="" width="837" height="294" data-recalc-dims="1" /></a><p id="caption-attachment-1045" class="wp-caption-text">좌: 기준선과 평행한 직선들 우: 기준선과 수직인 직선들</p></div></p>
  577. <p>예를 들어서 위의 이미지에서 빨간색 직선이 사각형의 한 변이라고 가정하고, 나머지 직선들을 살펴봅시다. 수직인 직선들을 1, 2, 3번이라고 표시해 두었습니다. 우선 1번과 2번 직선을 뽑아서 평가해 봅시다. 두 직선은 서로 거의 평행이기 때문에 사각형의 마주 보는 두 변이라고 해도 좋을 정도입니다. 하지만 두 직선 사이의 거리를 구해보니, 너무 가까이 붙어있어서 이 두 직선이 사각형의 마주 보는 두 변이라고 판단하기는 어렵습니다. 그렇다면 2번 직선을 두고, 1번과 3번 직선을 바라보면 어떨까요? 두 직선은 기준선과도 수직이고, 서로 평행하며 적당한 거리만큼 떨어져 있습니다. 그렇다면 1번과 3번 직선은 기준선과 함께 직사각형을 이루고 있을 수 있다고 판단하는 것입니다. 이렇게 기준선과 수직인 직선의 쌍을 찾아냈으면, 이들을 왼쪽 이미지에 있는 모든 평행한 직선과 조합해보면서 직사각형이 될 수 없는 조합들을 탈락시킵니다. 이렇게 상대적인 위치를 기준으로 직사각형이 될 수 있는 4개의 직선의 조합들을 찾을 수 있습니다.</p>
  578. <p>이렇게 만들어진 직선의 조합들을 모두 합당한 명함이라고 보기는 어려울 것입니다. 그래서 직사각형의 후보군을 가지고 형태가 너무 일그러져 있지는 않은지, 저희가 찾고자 하는 평균적인 명함의 비율(1 : 1.8)과 너무 크게 벗어나지는 않는지를 확인합니다. 그렇게 해서 남은 직사각형들 중 가장 큰 직사각형을 명함이라고 판단합니다. 이 모든 과정을 거치면 아래 그림과 같이 아주 깔끔하게 명함을 찾을 수 있습니다.</p>
  579. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?ssl=1"><img data-attachment-id="1047" data-permalink="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/blog_result_1/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?fit=956%2C706&amp;ssl=1" data-orig-size="956,706" 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="blog_result_1" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?resize=449%2C304&amp;ssl=1" class=" wp-image-1047 aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?resize=328%2C249&#038;ssl=1" alt="" width="328" height="249" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?resize=290%2C220&amp;ssl=1 290w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/blog_result_1.png?zoom=2&amp;resize=328%2C249&amp;ssl=1 656w" sizes="(max-width: 328px) 100vw, 328px" data-recalc-dims="1" /></a></p>
  580. <p>&nbsp;</p>
  581. <h1 id="OpenCV를이용한명함인식알고리즘개발-맺으며">맺으며</h1>
  582. <p>리멤버의 명함 인식 기능은 많은 시행착오를 통해서 만들어졌습니다. 수없이 많은 환경에서 촬영을 하며 필터값을 조정하고, 최대한 Edge case를 걷어낼 수 있는 로직을 추가해 나갔습니다. 이 블로그 글이 마법처럼 코드 한 줄로 돌아가는 명함 인식 기능을 소개해드리지는 못하지만, 비슷한 목표를 가진 분들께 좋은 출발점이 되기를 바랍니다.</p>
  583. <p>사용자들에게 최대한 빠르게 보다 좋은 퀄리티의 이미지를 제공하기 위해서는 앞으로도 갈 길이 멉니다. 좀 더 다양한 환경에서 더 정확하게 명함 이미지를 크랍해내야 하고, 잘라낸 이미지를 타이피스트가 읽기 쉽게 깨끗하게 가공하고 필터링하는 것도 고도화해 나가야 합니다. 더 나아가서는 가로 명함과 세로 명함을 구분 짓고, OCR을 통해 실시간으로 명함 정보를 읽어내는 것도 저희의 남은 과제입니다. 앞으로 계속해서 발전해나갈 리멤버의 카메라를 기대해주세요.</p>
  584. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/">리멤버는 어떻게 명함을 정확히 인식할까? : OpenCV 이미지 프로세싱</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  585. ]]></content:encoded>
  586. <wfw:commentRss>https://blog.dramancompany.com/2019/03/opencv%eb%a1%9c-%ec%8b%a4%ec%8b%9c%ea%b0%84-%eb%aa%85%ed%95%a8-%ec%9d%b8%ec%8b%9d%ed%95%98%ea%b8%b0/feed/</wfw:commentRss>
  587. <slash:comments>3</slash:comments>
  588. <post-id xmlns="com-wordpress:feed-additions:1">1016</post-id> </item>
  589. <item>
  590. <title>리멤버 QA팀이 하는 일</title>
  591. <link>https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/</link>
  592. <comments>https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/#comments</comments>
  593. <pubDate>Mon, 18 Mar 2019 09:16:13 +0000</pubDate>
  594. <dc:creator><![CDATA[sumin]]></dc:creator>
  595. <category><![CDATA[기술 블로그]]></category>
  596.  
  597. <guid isPermaLink="false">http://blog.dramancompany.com/?p=974</guid>
  598. <description><![CDATA[<p>안녕하세요. 드라마앤컴퍼니 QA팀 곽수민입니다. 이번 포스팅에서 드라마의 QA팀은 어떠한 업무를 하고 있는지 소개하려 합니다.  삐까뻔쩍한 최신형 휴대폰을 사용해보았더니, 막상 전화 거는 방법도 모르겠고, 키보드를 사용하는 방법도 어렵고, 기본으로 설치된 애플리케이션이 강제 종료되어 작업 중인 내용이 사라진다면 어떨까요? 소비자들로부터 품질 관련 불만이 봇물처럼 터져나오고 아무도 그 휴대폰을 구매하려고 하지 않을 것입니다. 그래서 개발 결과물에 대한 QA 검수가<a class="button" href="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/" title="Read More">Read more</a></p>
  599. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/">리멤버 QA팀이 하는 일</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  600. ]]></description>
  601. <content:encoded><![CDATA[<p style="text-align: left;">안녕하세요. 드라마앤컴퍼니 QA팀 곽수민입니다. <span style="font-weight: 400;">이번 포스팅에서 드라마의 QA팀은 어떠한 업무를 하고 있는지 소개하려 합니다. </span></p>
  602. <p style="text-align: left;"><span style="font-weight: 400;">삐까뻔쩍한 최신형 휴대폰을 사용해보았더니, 막상 전화 거는 방법도 모르겠고, 키보드를 사용하는 방법도 어렵고, 기본으로 설치된 애플리케이션이 강제 종료되어 작업 중인 내용이 사라진다면 어떨까요? 소비자들로부터 품질 관련 불만이 봇물처럼 터져나오고 아무도 그 휴대폰을 구매하려고 하지 않을 것입니다. 그래서 개발 결과물에 대한 QA 검수가 매우 중요합니다.</span></p>
  603. <p>QA 검수 단계에서는 크게 다음 두 가지 관점으로 검수를 진행합니다.</p>
  604. <ul>
  605. <li style="font-weight: 400;"><span style="font-weight: 400;">기능적 관점: 버그 없이 기능이 잘 동작하는지 </span></li>
  606. <li style="font-weight: 400;"><span style="font-weight: 400;">사용자 UI/UX 관점: 각종 버튼/텍스트/화면 레이아웃 등 </span>UI가 올바르게 표시되는지</li>
  607. </ul>
  608. <p><b>UX가 잘 설계되었는지 여부</b><span style="font-weight: 400;">는 기획자 분들도 이미 많은 고민을 하신 이유로 QA 검수를 넘어서 판단하기 조심스러운 영역인 것 같습니다.</span></p>
  609. <p style="text-align: center;"><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?ssl=1"><img data-attachment-id="1055" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/network-1987209_960_720/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?fit=960%2C640&amp;ssl=1" data-orig-size="960,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="network-1987209_960_720" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-1055" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?resize=960%2C640&#038;ssl=1" alt="" width="960" height="640" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?w=960&amp;ssl=1 960w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/network-1987209_960_720.jpg?resize=768%2C512&amp;ssl=1 768w" sizes="(max-width: 960px) 100vw, 960px" data-recalc-dims="1" /></a></p>
  610. <p>QA 검수는 정확성이 생명이기 때문에 최대한 효율적이고, 넓은 테스트 Coverage를 가지고 진행되어야 합니다. 검수가 제대로 이루어지지 않는다면 서비스의 품질과 사용자 Retention은 낮아지고, 결국 사용자에게 사랑받지 못하는 서비스가 되고 맙니다. 따라서 드라마 QA팀에서는 더 정확하고 꼼꼼한 검수를 위해 다양한 방법을 사용하고 있습니다.</p>
  611. <p>&nbsp;</p>
  612. <p><strong>&#8211; QA의 꽃 : 기능 / UI 테스트</strong></p>
  613. <p><span style="font-weight: 400;">안드로이드 디바이스는 이슈에 따라 디바이스 또는 OS 환경에 영향을 받는 경우가 매우 많습니다. (저는 그래서 iOS 검수를 좋아하는 편입니다.) 정확히 추산할 수 없지만, 리멤버의 구글 플레이 스토어 배포 단계에서 설치 가능한 디바이스들을 조회해보면 약 11,500개 정도의 디바이스들이 보여집니다. 그러니 전세계의 안드로이드 디바이스들을 모두 전수 테스트한다는 것은 말도 안되는 일이죠. 그래서 사용자들이 많이 사용하는 디바이스들을 고려하여, 비교적 넓은 Coverage를 가진 범용적인 디바이스들로 테스트 기기를 선정하는 것이 매우 중요합니다. (다행히 한국은 삼성에서 나온 디바이스들의 점유율이 높아 어렵지는 않았습니다.)</span></p>
  614. <p><span style="font-weight: 400;">테스트 기기 선정을 마쳤다면, 테스트 시나리오도 준비합니다. 보통 모든 기능을 테스트하는 전수테스트(Full 테스트)와 각 기능별 주요 요소를 빠르게 점검하기 위한 기능테스트(Simple 테스트)가 있습니다. 그 외 배포 후 빠르게 UI 요소들을 점검할 수 있는 테스트 시나리오, 테스트 환경 (QA 검수 환경, Staging 환경, 운영 환경 등)에 따른 테스트 시나리오도 있습니다. 다양한 상황에서 다양한 목적으로 테스트할 수 있도록 여러 테스트 시나리오를 만들고, 이를 상황에 맞게 적절히 조합하여 활용하는 것이 중요합니다.</span></p>
  615. <p><span style="font-weight: 400;">이제 테스트를 진행합니다. 구현된 기능은 문제가 없는지, 다양한 환경에서 앱이 잘 구동되는지의 여부, 레이아웃이나 워딩 등에 문제는 없는지, 입력된 데이터는 정상적으로 등록되어 앱에 표시되는지 등의 사용자 케이스를 충분히 고려하면서 검수를 진행하게 됩니다.</span></p>
  616. <p>&nbsp;</p>
  617. <p><span style="font-weight: 400;">사실 위에서 언급한 QA 검수는 모든 QA 조직에서 잘하고 계신 부분입니다.  </span><span style="font-weight: 400;">그러나 드라마 QA팀에는 다른 조직과는 구별되는 여러 특징들이 존재합니다. 그 중 첫 번째는 바로 서버 API를 QA검수와 버그 원인 추적에 매우 잘 활용한다는 것입니다.</span></p>
  618. <p>&nbsp;</p>
  619. <p><strong>&#8211; 최고의 보조 도구 : API</strong></p>
  620. <p><span style="font-weight: 400;">서비스마다 차이가 있지만, 리멤버에서는 로컬에서만 동작 가능한 기능도 있고, API 라는 서버와의 통신을 통해 앱을 조종하는(?) 녀석이 있습니다. 저도 이 API 영역이 처음에는 매우 어렵고, 개발자들만 아는 기술인 줄 알았습니다. </span></p>
  621. <p><span style="font-weight: 400;">보통 테스트 업무를 하기 위해서 테스트용 더미 데이터를 쌓거나, 수십개의 계정이 필요한 경우들이 있습니다. 또한, 버그의 내용 파악을 위해서 ‘노가다’로 재현단계에 필요한 데이터를 쌓거나, 부족한 정보들로 파악해볼 수 밖에 없습니다. 저도 역시 그러한 과정을 통해서 많은 시간을 날려(?)보았던 경험이 있습니다. 더 나은 프로세스를 만들기 위해서 여러가지 방법을 찾아본 끝에 내부 API를 활용해보기로 하였고, 결과는 상상을 초월할 정도로 QA 업무에 많은 도움이 되었습니다.</span></p>
  622. <p><span style="font-weight: 400;">보통 식당에서는 손님이 메뉴판에서 원하는 메뉴를 골라 직원에게 주문을 합니다, 그러면 주방에서는 요리를 하고, 음식이 완성되면 직원이 손님에게 가져다줍니다. 이를 API 개념에 빗대어보면 다음과 같습니다.</span></p>
  623. <p style="text-align: center;"><span style="font-weight: 400;">‘손님’ = ‘클라이언트’,</span></p>
  624. <p style="text-align: center;"><span style="font-weight: 400;">‘메뉴’ = ‘서비스가 제공하는 기능&#8217;,</span></p>
  625. <p style="text-align: center;"><span style="font-weight: 400;">‘주방’ = ‘서버&#8217;,</span></p>
  626. <p style="text-align: center;"><span style="font-weight: 400;">‘직원&#8217; = ’API’</span></p>
  627. <p><span style="font-weight: 400;">손님(클라이언트)은 주방(서버)에서 메뉴(기능)가 어떻게 만들어지는지 모르고 또 알 필요도 없습니다. 다만, 손님은 직원(API)을 통해서 요청(주문)을 보낼 수 있고, 요청의 결과(직원이 내가 주문한 메뉴를 가져다주는지)가 정상인지 확인할 수 있습니다. 예를 들면 우리는 서비스에 로그인을 하기 위해, 로그인 버튼을 누릅니다. 그러면 사용자 입장에서는 그냥 ‘로그인&#8217; 버튼만 눌렀다고 인지하게 됩니다. 하지만 실제로 우리가 주목해야 될 내용은</span></p>
  628. <ul>
  629. <li style="font-weight: 400;"><span style="font-weight: 400;">‘화면에서 보이는 버튼 중 로그인 버튼을 누름&#8217;  = ‘</span><b>로그인 요청 API를 서버로 전송</b><span style="font-weight: 400;">&#8216;</span></li>
  630. </ul>
  631. <p><span style="font-weight: 400;">입니다. (당연히 ‘로그인’ 버튼을 눌렀는데, ‘회원가입&#8217; API가 호출되면 안 됩니다. 식당에서 부대찌개를 시켰는데, 김치찌개가 나오면 안되잖아요?)</span></p>
  632. <p><span style="font-weight: 400;">API를 활용할 줄 알면 단순히 화면을 보고, 테스트 시나리오대로 검증하는 역할을 넘어서, 다양한 QA 업무를 더욱 단순하고 빠르게 해결할 수 있습니다. 드라마 QA팀은 팀명함첩 결제 기능처럼 복잡하거나, 반복적으로 이루어지는 테스트에 API를 활용하고 있습니다. 대량의 테스트 데이터를 만들 때도 사용합니다. 프로세스에 대한 고도화가 점점 되어가면서 테스트 API 서버가 여러 번 뻗기도 하였고, 생각지도 못한 기능들의 문제들도 발견할 수 있었습니다. (때문에 서버 개발팀이 고생 많이 하셨죠..) </span><span style="font-weight: 400;">그 외에도 사용자 혹은 사내에서 보고되는 버그들의 원인 파악에도 유용하고 쓰고 있습니다. 그 결과 노가다성 업무들은 60%이상 줄게 되었습니다.</span></p>
  633. <p style="text-align: center;"><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.25.25.png?ssl=1"><img data-attachment-id="978" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/%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-2019-03-18-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-25-25/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.25.25.png?fit=389%2C398&amp;ssl=1" data-orig-size="389,398" 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="스크린샷 2019-03-18 오후 5.25.25" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.25.25.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.25.25.png?resize=389%2C304&amp;ssl=1" class="alignnone size-full wp-image-978" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.25.25.png?resize=389%2C398&#038;ssl=1" alt="" width="389" height="398" data-recalc-dims="1" /></a></p>
  634. <p style="text-align: center;"><span style="font-weight: 400;">&lt;회원가입_인증번호 전송을 위한 API 호출&gt;</span></p>
  635. <p><span style="font-weight: 400;">위 이미지에서와 같이 API 호출 시 파라미터에 유효한 값, 유효하지 않은 값 등 다양한 값을 입력하고, 서버의 응답 결과를 확인합니다. 이를 통해 기능 요구사항에 맞는 API가 호출되는지, 앱에서는 API 응답을 화면에 잘 보여주는지 등을 확인해보면 실제로 소스 코드에 버그가 있는지, 그 원인은 무엇인지 파악할 수 있습니다.</span></p>
  636. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?ssl=1"><img data-attachment-id="1010" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2019-03-13-%ec%98%a4%ed%9b%84-12-38-49/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?fit=944%2C920&amp;ssl=1" data-orig-size="944,920" 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="스크린샷-2019-03-13-오후-12.38.49" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1010 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?resize=381%2C372&#038;ssl=1" alt="" width="381" height="372" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?w=944&amp;ssl=1 944w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-13-오후-12.38.49.jpg?resize=768%2C748&amp;ssl=1 768w" sizes="(max-width: 381px) 100vw, 381px" data-recalc-dims="1" /></a></p>
  637. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?ssl=1"><img data-attachment-id="1008" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/%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-2019-03-18-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-6-53-41/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?fit=932%2C1454&amp;ssl=1" data-orig-size="932,1454" 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="스크린샷 2019-03-18 오후 6.53.41" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-1008 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?resize=399%2C622&#038;ssl=1" alt="" width="399" height="622" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?w=932&amp;ssl=1 932w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-6.53.41.png?resize=768%2C1198&amp;ssl=1 768w" sizes="(max-width: 399px) 100vw, 399px" data-recalc-dims="1" /></a></p>
  638. <p style="text-align: center;"><span style="font-weight: 400;">&lt;내부에서 신고된 버그를 해결해나가는 과정&gt;</span></p>
  639. <p><span style="font-weight: 400;">테스트 중 발견되거나 사용자에게 제보된 버그들을 전달할 때, “이거 안되는거 같아요&#8221;라고 단순하게 전하기 보다는 “API 호출을 해보니 서버에서는 정상적으로 잘 처리가 되는 걸 보면 앱에 문제가 있는 것 같아요”하고 더욱 구체적인 내용을 전달해줄 수 있습니다. 덕분에 버그의 원인을 빠르게 잡아내고, 사용자의 불편함을 원활하게 해결하고 있습니다. </span></p>
  640. <p><span style="font-weight: 400;">개발팀 외 다른 팀이 서버 API의 내용을 잘 숙지하고 활용하면 조직 전체에 매우 큰 도움이 되는 것을 보여주는 사례이기도 합니다.</span></p>
  641. <p>&nbsp;</p>
  642. <p><b>자체 TASK</b></p>
  643. <p><span style="font-weight: 400;">1. 기능별 시나리오 분할과 Function-Tree</span></p>
  644. <p><span style="font-weight: 400;">드라마앤컴퍼니 QA 팀은 현재에 안주하지 않고 ‘일이 되게하는 방향&#8217;을 찾기 위해서 계속해서 시도하고, 빠르게 변화하는 업무 방식을 추구하고 있습니다. 예를 들면 과거 기능별 TF (하나의 기능 개발을 위해 기획, UI/UX, 개발, QA가 하나의 임시 팀을 이루는 것) 체제로 일을 한 적이 있었습니다. 이 때 여러 기능별 TF에서 각 기능 개발이 동시다발적으로 진행되면 QA팀의 리소스가 매우 부족했었습니다. 모든 기능을 매번 ‘전수 테스트&#8217; 한다는 것은 말도 안되는 엄청난 양이기도 하고, 매일 밤늦게까지 고생하면서 업무를 진행하기에는 팀원들의 사기도 매우 걱정이 되었습니다. 또한, 서비스에 기능이 계속 추가되면서 테스트 시나리오는 나날이 늘어만 가는 와중에 일정 수준의 테스트 Coverage를 만족시키는 것도 매우 부담스러웠습니다. 그에 더해 배포 주기도 점점 짧아지면서 기존의 시나리오로 매번 검증하는 방법은 너무 비효율적이었습니다.</span></p>
  645. <p><span style="font-weight: 400;">그래서 이를 해결해보고자 TF체제에 적합한 테스트 시나리오 관리 방법부터 고민했습니다. 우선 기존 전수테스트의 모든 Test Case들을 ‘기능&#8217; 단위별로 분할했습니다. 새롭게 추가되는 기능들도 같은 방식으로 모두 분할하여 관리하기 시작했습니다. (당연히 전수 테스트 시나리오에도 함께 반영이 되었고요.)</span></p>
  646. <p><span style="font-weight: 400;">이후에 각 TF에서 QA 검수를 요청하면 미리 검수용 시나리오를 분할해 둔 덕분에 해당 기능 및 연관된 기능만 테스트할 수 있었습니다. 이를 통해 테스트 범위를 대폭 축소시키면서도 일정한 수준의 Coverage를 확보할 수 있었습니다. QA 검수 효율이 매우 좋아지는 게 눈에 보였고, 더불어 팀의 리소스도 충분히 확보할 수 있었습니다.</span></p>
  647. <p><span style="font-weight: 400;">하지만 그 행복은 길지 않았습니다. 각 TF별로 단일 기능이 개발된 빌드의 검수가 필요할 때는 매우 적합했지만, 각 TF에서 개발한 여러 기능을 합친 빌드를 검수할 때가 문제였습니다. 분할된 기능의 테스트 시나리오를 일일이 찾아서 취합시켜야 하는 번거로움이 뒤따랐고, 테스트 결과의 History 관리가 매우 힘들다는 문제점이 있었습니다.</span></p>
  648. <p><span style="font-weight: 400;">사실상 테스트 시나리오를 일일이 찾아본다면 대응 가능하기도 하고, 여러 기능들이 합쳐져 검수해야 할 범위가 복합적이라면 전수 테스트를 돌려버리면 그만일수도 있습니다. 하지만 그만큼 코드 수정이 일어나지 않은 부분을 포함하여 불필요한 테스트를 반복하게 되면 아까운 테스트 리소스가 소모됩니다. 또, 광고, PR이나 마케팅 일정 등이 맞물려 배포 일정이 중요한 시기에 배포 타이밍을 놓치게 된다면 회사에 큰 손실을 입히게 됩니다. (여담이지만.. 그래서 QA팀은 정말 좋은 판단력을 지녀야 합니다. 어떻게 해서든 배포하기 전 완벽한 컨디션을 가진 서비스를 세상에 내놓아야 하니까요.)</span></p>
  649. <p><span style="font-weight: 400;">리멤버에서는 어떠한 기능을 수정 한다면, 똑같은 기능을 제공하는 다른 뷰, 또 다른 진입 Point, 숨어있는 관련 뷰 등이 많이 있습니다. 그래서 최소한의 Coverage를 유지하면서 모든 기능을 빠르고, 완벽하게 검수하는 방법을 찾아야 했습니다. 고민 끝에 서비스의 모든 기능과 기능 간 영향도를 한눈에 파악할 수 있도록 Function-Tree를 제작했습니다. (서비스의 기능이 추가/변경/삭제되면서 끝없는 현재 진행형입니다.)</span></p>
  650. <p style="text-align: center;"><b></b><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.28.35.png?ssl=1"><img data-attachment-id="982" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/%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-2019-03-18-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-28-35/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.28.35.png?fit=584%2C563&amp;ssl=1" data-orig-size="584,563" 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="스크린샷 2019-03-18 오후 5.28.35" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.28.35.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.28.35.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-982" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.28.35.png?resize=584%2C563&#038;ssl=1" alt="" width="584" height="563" data-recalc-dims="1" /></a></p>
  651. <p style="text-align: center;"><b>&lt;Function-Tree 사용 예시&gt;</b></p>
  652. <p><span style="font-weight: 400;">이렇게 간단하게 기능만 나열해놓은 것 같지만, 위의 사용 예시처럼 ‘이메일&#8217;에 대한 앱 내 모든 위치와 함께 코드 수정에 따른 영향도가 있을 만한 기능들을 한눈에 검색하여 파악할 수 있습니다. 이를 통해 테스트 범위를 정확하고 효율적으로 판단할 수 있음은 물론이고, 과거에 놓치고 있었던 부분까지 검증할 수 있었습니다.</span></p>
  653. <p>&nbsp;</p>
  654. <p><strong>2. 테스트 자동화(Test Automation)</strong></p>
  655. <p><span style="font-weight: 400;">시간이 흐름에 따라 서비스의 기능이 점점 늘어나면 테스트 범위도 함께 늘어납니다. 그런데 빡빡한 일정에 맞춰서 검수를 마치려면, 시간이 없다는 이유로 전체적인 Test Coverage를 타협해야 하는 경우도 많습니다. 하지만 이렇게 하면 문제를 발견하지 못할 확률이 높아지고 최상의 컨디션을 가진 제품을 보장하지 못합니다.</span></p>
  656. <p><span style="font-weight: 400;">드라마의 QA팀에서는 이러한 문제를 해결하고자 테스트 자동화를 도입하여 Appium 서버와 Selenium Library에 기반한 자동화 스크립트를 개발하고 있습니다.</span></p>
  657. <p style="text-align: center;"><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/temp_1552898906654.-1590457630.gif?ssl=1"><img data-attachment-id="988" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/temp_1552898906654-1590457630/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/temp_1552898906654.-1590457630.gif?fit=390%2C360&amp;ssl=1" data-orig-size="390,360" 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="temp_1552898906654.-1590457630" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/temp_1552898906654.-1590457630.gif?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/temp_1552898906654.-1590457630.gif?resize=390%2C304&amp;ssl=1" class="alignnone size-full wp-image-988" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/temp_1552898906654.-1590457630.gif?resize=390%2C360&#038;ssl=1" alt="" width="390" height="360" data-recalc-dims="1" /></a></p>
  658. <p style="text-align: center;"><span style="font-weight: 400;">&lt;자동화 스크립트가 작동되는 모습.gif&gt;</span></p>
  659. <p><span style="font-weight: 400;">테스트 시나리오 중 굳이 사람 손을 타지 않아도 되는 기능들을 테스트 자동화하면 테스트에 소요되는 리소스를 절감하고 테스트 속도를 크게 향상시킬 수 있습니다. 또한 QA 직무의 특성상 같은 시나리오로 테스트를 반복하다보면 지루해지기 쉽고, 그러면 실수할 수 있는 확률이 높아집니다. 그러나 스크립트는 사람과 달리 지루함을 느끼지도 않고, 실수하지도 않기 때문에, ‘일관성’ 있는 테스트 결과를 받아볼 수 있습니다. 또한, 자동화 스크립트가 점점 쌓여가면서 컴퓨터가 할 수 있는 Test Coverage가 점점 더 늘어나면, QA 엔지니어의 리소스를 테스트 시나리오 고도화 등 다른 더 가치 있는 작업에 사용할 수 있다는 장점이 있습니다.</span></p>
  660. <p><span style="font-weight: 400;">반면, 테스트 자동화의 단점은 기능의 추가/수정이 일어나면 관리해야 될 소스 코드의 양도 늘어난다는 것입니다. 추후에 대규모 UI 또는 기능 변경이 일어난다면 관련 코드를 수정해야 하므로 예상치 못한 큰 Cost가 발생할 수 있습니다. 따라서, 어떤 부분을 자동화하고, 어떤 부분을 하지 말아야 할 지 잘 판단해야 합니다.</span></p>
  661. <p>&nbsp;</p>
  662. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?ssl=1"><img data-attachment-id="987" data-permalink="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/%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-2019-03-18-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-5-43-07/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?fit=1972%2C1364&amp;ssl=1" data-orig-size="1972,1364" 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="스크린샷 2019-03-18 오후 5.43.07" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?resize=449%2C304&amp;ssl=1" class="alignnone wp-image-987 aligncenter" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?resize=905%2C626&#038;ssl=1" alt="" width="905" height="626" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?w=1972&amp;ssl=1 1972w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/스크린샷-2019-03-18-오후-5.43.07.png?resize=768%2C531&amp;ssl=1 768w" sizes="(max-width: 905px) 100vw, 905px" data-recalc-dims="1" /></a></p>
  663. <p style="text-align: center;"><span style="font-weight: 400;">&lt;실제 리멤버 앱에서 테스트가 수행되는 Step을 구현한 소스 일부&gt;</span></p>
  664. <p><span style="font-weight: 400;">스크립트는 ‘기본 기능 검증’ 위주로 작성해야 합니다. ‘기본 기능 검증&#8217; 은 여러가지 의미가 있을 수 있지만 저희는 보통 ‘Happy Path’(예외 또는 오류의 발생 없이 정상적으로 수행되는 기본 시나리오)로 설정하고 있습니다. 기획 내용을 바탕으로 예상한 대로 잘 동작하는지, 특정 상황에서 정의된 에러 메시지(ex. ‘비밀번호를 잘못 입력하셨습니다.’ 등의 메시지(API의 경우 200 OK 응답))가 잘 보여지는지 확인합니다. (참고로 예상치 못한 404, 500 등의 API 에러가 발생하는 경우는 ‘Happy Path’가 아닙니다.)</span></p>
  665. <p>‘Happy Path’ 위주의 검증 방법을 채택한 이유는 모든 테스트 시나리오에 대해 코드를 작성하면, 무수히 많은 Case들을 고려해야 하므로 결국은 사람이 직접 손으로 테스트를 하는 것보다 훨씬 더 비효율적이기 때문입니다. 너무 많은 테스트 케이스로 인한 스크립트 관리/유지보수의 부담과 Code Quality의 저하로 인해 사람의 손을 더 타게 된다면 배보다 배꼽이 더 큰 상황을 초래할 수 있습니다. <span style="font-weight: 400;">또한, 서비스 기능별로 ‘단위 테스트&#8217; 방식 기반으로 스크립트를 작성하였고, 때때로 전체 테스트가 필요하면 모든 단위 테스트를 한번에 모아서 ‘통합 테스트&#8217;를 실행하도록 시스템을 구축하였습니다. 이렇게 하면 마이너한 앱 기능 수정(전체 테스트가 필요 없는 코드 수정)이나 빠르게 해결되어야 하는 hotfix(긴급패치) 대응을 위한 테스트를 빠르게 진행하기 쉽습니다. </span></p>
  666. <p>이렇게 만들어진 Script는 마치 사람이 실제 앱을 사용하는 것처럼 클라이언트를 조작할 수 있고, 정의된 시나리오대로 앱의 기능 테스트를 수행하게 됩니다.</p>
  667. <p>&nbsp;</p>
  668. <p><b>마무리</b></p>
  669. <p><span style="font-weight: 400;">다음에는 위에 소개한 내용 중 드라마 QA팀이 자동화 시스템을 구축하면서 겪은 시행착오와 구축방법을 본격적으로 소개해보려고 합니다.</span></p>
  670. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/">리멤버 QA팀이 하는 일</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  671. ]]></content:encoded>
  672. <wfw:commentRss>https://blog.dramancompany.com/2019/03/%eb%93%9c%eb%9d%bc%eb%a7%88-qa%ed%8c%80%ec%9d%b4-%ed%95%98%eb%8a%94-%ec%9d%bc/feed/</wfw:commentRss>
  673. <slash:comments>9</slash:comments>
  674. <post-id xmlns="com-wordpress:feed-additions:1">974</post-id> </item>
  675. <item>
  676. <title>리멤버 지원자분들이 묻는 질문 Top 4</title>
  677. <link>https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/</link>
  678. <comments>https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/#respond</comments>
  679. <pubDate>Tue, 12 Mar 2019 05:16:08 +0000</pubDate>
  680. <dc:creator><![CDATA[Tom Kim]]></dc:creator>
  681. <category><![CDATA[기술 블로그]]></category>
  682.  
  683. <guid isPermaLink="false">http://blog.dramancompany.com/?p=966</guid>
  684. <description><![CDATA[<p>안녕하세요 정말 오랜만에 쓰는 글입니다. 글이 안올라와서 &#8220;이 회사 망한거 아니야?&#8221;라는 생각을 갖으셨을수도 있겠지만 그런건 아니고 지난 기간동안 리멤버는 큰 성장을 만들어내는데 정말 많이 바빴습니다. 핑계지만 바쁘다는 이유로 글을 거의 쓰지 못했습니다^^; 드라마앤컴퍼니도 대부분의 IT 업체와 마찬가지로 훌륭한 동료분을 모시기 위하여 개발자 채용에 매우 열심히 노력하고 있고 그 결과 면접도 많이 보고 있습니다. 면접에서 대부분의<a class="button" href="https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/" title="Read More">Read more</a></p>
  685. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/">리멤버 지원자분들이 묻는 질문 Top 4</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  686. ]]></description>
  687. <content:encoded><![CDATA[<p>안녕하세요 정말 오랜만에 쓰는 글입니다. 글이 안올라와서 &#8220;이 회사 망한거 아니야?&#8221;라는 생각을 갖으셨을수도 있겠지만 그런건 아니고 지난 기간동안 리멤버는 큰 성장을 만들어내는데 정말 많이 바빴습니다. 핑계지만 바쁘다는 이유로 글을 거의 쓰지 못했습니다^^;</p>
  688. <p>드라마앤컴퍼니도 대부분의 IT 업체와 마찬가지로 훌륭한 동료분을 모시기 위하여 개발자 채용에 매우 열심히 노력하고 있고 그 결과 면접도 많이 보고 있습니다. 면접에서 대부분의 지원자분들이 항상 공통적으로 물어봐주시는 질문이 있습니다. 지원하시기 전에 제대로 알려드리지 못한 저희의 잘못도 크고 매번 같은 얘기를 하는 것 보다는 글로 정리하는 것이 훨씬 효율적일 것 같다고 생각하여 이번 글에서는 서버 파트 지원자분들께 자주 받는 질문 4개와 그에 대한 답변을 정리해보고자 합니다.</p>
  689. <p>&nbsp;</p>
  690. <h2>[질문 1] 왜 Ruby on Rails를 사용하나요?</h2>
  691. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/rails.png?ssl=1"><img data-attachment-id="967" data-permalink="https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/rails/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/rails.png?fit=300%2C105&amp;ssl=1" data-orig-size="300,105" 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="rails" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/rails.png?resize=290%2C105&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/rails.png?resize=300%2C105&amp;ssl=1" class="size-full wp-image-967 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/rails.png?resize=300%2C105&#038;ssl=1" alt="" width="300" height="105" data-recalc-dims="1" /></a></p>
  692. <p>우선 드라마앤컴퍼니에서는 API, 어드민, 리멤버 Web 버전을 포함한 거의 모든 백엔드 프로젝트에 Ruby 언어와 Ruby on Rails(이하 RoR) 프레임워크를 사용하고 있습니다. 이 질문은 &#8220;저 Ruby 안 해봤는데 괜찮은가요?&#8221;, &#8220;언제 다른 언어로 바꾸나요?&#8221; 등의 질문과 함께 가장 많이 받는 질문입니다. 아무래도 국내에서는 Java가 압도적으로 대세인 언어이고, Ruby보다는 Python이나 Node.js가 더 인기가 많다 보니 Ruby라는 언어를 굉장히 생소하고 낯설게 느끼시는 분들이 많은 것 같습니다. 물론 저도 처음에는 그랬고요.</p>
  693. <p>드라마앤컴퍼니는 회사를 처음 시작할 때부터 RoR을 사용했습니다. 기존에 Java 개발자셨던 분이 리멤버를 만들 때쯤 RoR를 접하고 엄청난 생산성에 반해 API, 타이피스트, 어드민 등 모든 시스템을 RoR로 만드셨습니다. 이분 이후로도 드라마앤컴퍼니에서 RoR를 사용하셨던 개발자분들이 10명이 넘는데, 한 분을 제외하고는 Ruby에 대해 거의 아무것도 모르는 상태로 입사하셨습니다.</p>
  694. <p>저희는 언어와 프레임워크는 모두 &#8220;도구&#8221;일 뿐이라고 생각합니다. 그리고 &#8220;뛰어난 개발자는 어떤 도구를 사용해도 잘한다.&#8221;라는 생각이 있죠. 물론 언어와 프레임워크에 대한 이해도도 매우 중요하기 때문에 그 도구를 제대로 사용하기 위해서는 어느 정도의 숙련이 필요한 것이 사실입니다. 따라서 아무리 뛰어난 개발자여도 처음 하는 언어와 프레임워크를 접하면 처음에는 좋은 품질의 코드를 만들기 힘들다고 생각합니다.</p>
  695. <p>하지만 저희는 기존 코드도 계속 리팩토링하면서 완성도를 높여왔으며 테스트 코드와 문서화도 꽤 잘되어있는 편이기 때문에 한 가지 이상의 언어에 능통하시고 뛰어난 개발자라면 1주일도 안 돼서 좋은 코드를 만드실 수 있는 환경이라고 생각합니다.</p>
  696. <p>&#8220;RoR은 매우 느리기 때문에 바꿔야 하지 않는가?&#8221;라는 질문도 있습니다. 물론 같은 로직을 구현하는 경우 C나 Java에 비해 느린 것이 사실입니다. 하지만 애플리케이션이 느린 원인은 언어의 성능보다는 사람이 만든 로직이나 설계에 있는 경우가 훨씬 많습니다. 그리고 리멤버가 온라인 게임이나 대규모 메시징 앱처럼 실시간 속도가 엄청나게 중요한 서비스가 아니기 때문에 이 부분은 크게 문제 되지 않는다고 생각합니다.</p>
  697. <p>GitHub, Airbnb, Twitter, Twitch 등 세계적으로 큰 회사들이 지금도 혹은 국내에서 접할 수 있는 것보다 훨씬 큰 규모의 서비스가 될 때까지 RoR를 메인 프레임워크로 사용한 것을 보면 한동안은 계속 사용할 수 있다고 생각합니다. 그리고 무엇보다도 사내에서 RoR을 제대로 사용해보신 분들은 모두 RoR의 편의성과 생산성에 대해 매우 만족해하고 있습니다.</p>
  698. <p>&nbsp;</p>
  699. <h2>[질문 2] 기술 스택이 어떻게 되나요?</h2>
  700. <p>우선 앞서 말씀드린 것처럼 웹 프레임워크로는 Ruby on Rails를 사용하고 있습니다. 그리고 인프라는 AWS, 인 메모리 DB는 Redis, 로그 관리는 ELK stack, APM은 NewRelic, 비동기 job 처리는 Sidekiq, 테스트 프레임웍은 Rspec을 사용하고 있습니다. 그리고 이 기술들을 어느 정도는 잘 쓰고 있다고 생각합니다.</p>
  701. <p>예를 들어 RoR과 같은 경우 여러 번 리팩토링을 거치면서 더 나은 코드 구조를 만들기 위해 노력하고 있으며 거의 모든 경우 테스트 코드를 작성하고 있습니다. 그 결과 API의 메인 프로젝트의 테스트 코드의 수만 7,000개가 넘습니다.</p>
  702. <p>AWS의 경우 기본적인 EC2와 S3부터 Lambda, SQS, Route 53, API Gateway, CloudWatch, CodeDeploy, CodePipeline, CodeBuild, ElastiCache, ElasticBeanstalk, ECR 등 많은 서비스를 사용하고 있습니다. 다음은 저희가 AWS를 잘 활용하고 있다고 생각하는 몇 가지 예시들입니다.</p>
  703. <ul>
  704. <li>Auto Scaling으로 API 서버의 인스턴스의 수가 매일 3대에서 70대까지 변합니다.</li>
  705. <li>데일리 컨텐츠 푸시를 위하여 주중 아침마다 AWS SNS를 이용하여 200만 개 이상의 디바이스에 푸시를 한 번에 발송합니다.</li>
  706. <li>테스트 코드가 많다 보니 테스트 코드를 실행하는 데만 2시간이 걸리기 때문에 Jenkins, CodeBuild, ECR을 이용하여 BuildFarm을 만들었습니다. CodeBuild를 이용하여 원하는 수 만큼의 Slave를 만들어 병렬로 테스트 코드를 돌립니다.</li>
  707. </ul>
  708. <p>&nbsp;</p>
  709. <h2>[질문 3] 어떤 개발 문화를 갖고 있나요?</h2>
  710. <p>우선 첫 번째 회고와 오버 커뮤니케이션을 굉장히 중요하게 생각합니다. 저희는 팀의 규모가 작을때 부터 커진 지금도 주기적인 회고를 통하여 어떤 문제점이 있는지 발견하고 그 문제점을 개선하기 위하여 계속 노력합니다. 그 결과 개발팀이 5명도 안되게 작을때부터 20명이된 지금까지 끊임없이 현재 저희에게 맞는 업무 구조와 프로세스를 찾기 위하여 많은 변화를 시도했습니다.</p>
  711. <p>오버 커뮤니케이션을 위해 매일 아침마다 제품 개발에 관련된 모든 인원이 모여 데일리 스크럼 미팅을 진행합니다. 개발, 기획, 디자인 팀 구성원들이 보여서 회사에 크게 진행되고 있는 이슈들에 대해서 진행 상황과 문제 상황등을 동기화하는 시간을 갖습니다. 그리고 업무시간 종료 직전에 하루 일과에 대한 공유 시간을 갖습니다. 오늘은 어떤 일이 진행됐고 어떤 문제가 있는지를 동기화하면서 서로 도움을 줄 수 있는 부분을 찾습니다.</p>
  712. <p>회고와 오버커뮤니케이션에 대해서는 드라마앤컴퍼니 CTO이신 세준님의 <a href="https://post.naver.com/viewer/postView.nhn?volumeNo=17104973&amp;memberNo=39874958">사내 인터뷰</a>에(https://post.naver.com/viewer/postView.nhn?volumeNo=17104973&amp;memberNo=39874958)서 더 자세하게 확인하실 수 있습니다.</p>
  713. <p>두 번째 페어 프로그래밍, 코드 리뷰를 적극 활용합니다. 페어 프로그래밍과 코드 리뷰 모두 장단점을 갖고 있는 방법입니다. 개발자가 한 명이 개발에 집중할 수 있는 시간이 줄어든다는 단점이 있지만 업무 스타일이나 코딩 스타일, 다른 사람이 작업한 영역 등을 굉장히 효율적으로 동기화할 수 있고 까다로운 작업을 할 땐 버그의 위험성을 매우 낮춰주는 등 많은 장점들이 있습니다. 모든 일에 대해 적용한다면 매우 비효율적이겠지만 특정 상황에서는 이만큼의 좋은 효율성을 내는 방법도 없다고 생각합니다. 저희는 이 방법론이 가장 큰 효율을 낼 수 있을 때마다 잘 사용하고 있습니다.</p>
  714. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?ssl=1"><img data-attachment-id="968" data-permalink="https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/pr/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?fit=1996%2C1558&amp;ssl=1" data-orig-size="1996,1558" 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="pr" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?resize=449%2C304&amp;ssl=1" class="size-full wp-image-968 aligncenter" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?resize=1170%2C913&#038;ssl=1" alt="" width="1170" height="913" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?w=1996&amp;ssl=1 1996w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2019/03/pr.png?resize=768%2C599&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  715. <p>세 번째 문서화가 매우 잘 되어있습니다. 웬만한 업무는 다 Jira 이슈로 관리되며 처리된 내용은 Jira 이슈나 Confluence Wiki 페이지로 관리됩니다. Wiki 페이지, Git 커밋 메시지, Pull Request, 릴리즈 노트 등 모든 곳에 지라 이슈 번호가 따라다닙니다. 서식을 맞추는 데 힘을 빼는 문서화가 아닌 기록을 위한 문서로 만듭니다. 최대한 힘을 안 들이고 쓰되 나중에 이 이슈를 다시 봐야 하는 경우 이 당시 상황을 이해할 수 있을 정도로만 문서를 작성합니다.</p>
  716. <p>마지막으로 기술을 제대로 사용할 줄 아는 팀이라고 생각합니다. 개발자가 더 나은 기술을 좇는 것은 좋은 자세지만 이 자세가 과하면 일을 망치는 경우가 많습니다. 기술은 개발자 개인의 만족감을 채워주는 것이 아니라 우리 이루고자 하는 목적을 위해 필요한 것입니다. 따라서 많은 개발자가 쉽게 빠질 수 있는 오버 엔지니어링과 Hype Driven Development(설레발 주도 개발)은 피합니다. 그렇다고 절대로 과거 기술에만 머물러있지는 않습니다. 신기술들을 계속 살펴보며 우리에게 정말 도움이 된다면 바로 사용합니다. 예를 들어 몇 년전 Electron의 아직 정식 버전이 나오기도 전에 리멤버 웹 버전의 데스크톱 개발을 위하여 사용하여 좋은 리텐션 증가를 만들어낸 이력이 있습니다. 기술을 사용하는 이 부분에 대한 보다 자세한 내용은 제가 한 <a href="https://post.naver.com/viewer/postView.nhn?volumeNo=17322226&amp;memberNo=39874958">사내 인터뷰 글</a>(https://post.naver.com/viewer/postView.nhn?volumeNo=17322226&amp;memberNo=39874958)에서 더 자세하게 확인하실 수 있습니다.</p>
  717. <p>&nbsp;</p>
  718. <h2>[질문 4] 앞으로 리멤버의 계획은 어떻게 되나요?</h2>
  719. <p>지금까지의 리멤버는 명함관리 유틸리티일 뿐이었지만 저희는 단 한 번도 명함관리앱을 최종 목표로 삼은 적이 없습니다. 이미 그 다음 단계로 넘어가기 위한 작업이 한창입니다. 여기서 모든 내용을 설명하자면 글이 너무 길어질 것 같으니 자세한 건 다음 기사들을 읽어보시면 도움이 될 것 같습니다.</p>
  720. <p><a href="https://news.joins.com/article/23401613">[단독] 네이버 리멤버, 명함관리 넘어 ‘한국판 링크드인’ 띄운다</a> (https://news.joins.com/article/23401613)</p>
  721. <p><a href="http://www.etnews.com/20181119000331">믿을만한 전문가 찾는다면…명함 앱 리멤버, 매칭 서비스 출시</a> (http://www.etnews.com/20181119000331)</p>
  722. <p><a href="http://view.asiae.co.kr/news/view.htm?idxno=2019020715282622041">[히든히어로즈(39)] &#8220;앞으론 리멤버에서 인맥 찾으세요&#8221;</a> (http://view.asiae.co.kr/news/view.htm?idxno=2019020715282622041)</p>
  723. <p>&nbsp;</p>
  724. <h2>[마무리]</h2>
  725. <p>이 글을 보시고 리멤버에 대한 궁금증이 조금 풀리셨길 기대해봅니다. 혹시 이 글을 보시고 리멤버에서 함께 일하고 싶은 마음이 생기셨다면 주저말고 지원 해주시길 바랍니다. <a href="http://dramancompany.com/joinus/">http://dramancompany.com/joinus/</a> 페이지에서 리쿠르팅중인 포지션에 대한 보다 자세한 내용을 확인하실 수 있습니다.</p>
  726. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/">리멤버 지원자분들이 묻는 질문 Top 4</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  727. ]]></content:encoded>
  728. <wfw:commentRss>https://blog.dramancompany.com/2019/03/%eb%a6%ac%eb%a9%a4%eb%b2%84-%ec%a7%80%ec%9b%90%ec%9e%90%eb%b6%84%eb%93%a4%ec%9d%b4-%eb%ac%bb%eb%8a%94-%ec%a7%88%eb%ac%b8-top-4/feed/</wfw:commentRss>
  729. <slash:comments>0</slash:comments>
  730. <post-id xmlns="com-wordpress:feed-additions:1">966</post-id> </item>
  731. <item>
  732. <title>Fabric Branch로 사용자 행동 분석하기</title>
  733. <link>https://blog.dramancompany.com/2018/04/fabric-branch%eb%a1%9c-%ec%82%ac%ec%9a%a9%ec%9e%90-%ed%96%89%eb%8f%99-%eb%b6%84%ec%84%9d%ed%95%98%ea%b8%b0/</link>
  734. <comments>https://blog.dramancompany.com/2018/04/fabric-branch%eb%a1%9c-%ec%82%ac%ec%9a%a9%ec%9e%90-%ed%96%89%eb%8f%99-%eb%b6%84%ec%84%9d%ed%95%98%ea%b8%b0/#respond</comments>
  735. <pubDate>Fri, 20 Apr 2018 02:39:37 +0000</pubDate>
  736. <dc:creator><![CDATA[rfrost]]></dc:creator>
  737. <category><![CDATA[기술 블로그]]></category>
  738.  
  739. <guid isPermaLink="false">http://blog.dramancompany.com/?p=934</guid>
  740. <description><![CDATA[<p>Fabric Branch 사용 배경 대부분의 회사는 마케팅을 합니다. 그리고 서비스를 운영하는 회사는 퍼포먼스 마케팅을 합니다. 퍼포먼스 마케팅이란? 홍보뿐만 아니라 원하는 행동을 유도하는 마케팅 입니다. 퍼포먼스 마케팅에서 중요한 것은 캠페인을 통해 원하는 행동을 얼마나 잘 유도하였나 측정하는 것입니다. 측정을 어떤식으로 하는지, 마케팅 채널 별 신규유입을 측정 하는 것으로 예시를 들어보겠습니다. (1) 마케팅으로 사용할 스토어 링크에 레퍼러를 삽입합니다.<a class="button" href="https://blog.dramancompany.com/2018/04/fabric-branch%eb%a1%9c-%ec%82%ac%ec%9a%a9%ec%9e%90-%ed%96%89%eb%8f%99-%eb%b6%84%ec%84%9d%ed%95%98%ea%b8%b0/" title="Read More">Read more</a></p>
  741. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2018/04/fabric-branch%eb%a1%9c-%ec%82%ac%ec%9a%a9%ec%9e%90-%ed%96%89%eb%8f%99-%eb%b6%84%ec%84%9d%ed%95%98%ea%b8%b0/">Fabric Branch로 사용자 행동 분석하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  742. ]]></description>
  743. <content:encoded><![CDATA[<section class="section section--body">
  744. <h1 class="section-divider">Fabric Branch 사용 배경</h1>
  745. <div class="section-content">
  746. <div class="section-inner sectionLayout--insetColumn">
  747. <p class="graf graf--p">대부분의 회사는 마케팅을 합니다. 그리고 서비스를 운영하는 회사는 퍼포먼스 마케팅을 합니다.</p>
  748. <figure class="graf graf--figure"><img class="graf-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1600/1*3WmEk8QT7uCdszO0isqwwA.jpeg?resize=1170%2C656&#038;ssl=1" data-image-id="1*3WmEk8QT7uCdszO0isqwwA.jpeg" data-width="5443" data-height="3054" data-recalc-dims="1" /></figure>
  749. <h3 class="graf graf--h4">퍼포먼스 마케팅이란?</h3>
  750. <p class="graf graf--p">홍보뿐만 아니라 원하는 행동을 유도하는 마케팅 입니다. 퍼포먼스 마케팅에서 중요한 것은 캠페인을 통해 원하는 행동을 얼마나 잘 유도하였나 측정하는 것입니다. 측정을 어떤식으로 하는지, 마케팅 채널 별 신규유입을 측정 하는 것으로 예시를 들어보겠습니다.</p>
  751. <p class="graf graf--p">(1) 마케팅으로 사용할 스토어 링크에 레퍼러를 삽입합니다.</p>
  752. <figure class="graf graf--figure">
  753. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1600/1*pnQIE0wVrxHHYjQjPbwlLA.png?resize=1170%2C176&#038;ssl=1" alt="" width="1170" height="176" data-image-id="1*pnQIE0wVrxHHYjQjPbwlLA.png" data-width="2034" data-height="306" data-recalc-dims="1" /><p class="wp-caption-text">스토어 링크에 utm 속성을 붙입니다.</p></div></figure>
  754. <p class="graf graf--p">(2) 레퍼러가 삽입된 링크를 통해 스토어에 들어오면 콘솔에 레퍼러 속성이 기록됩니다.</p>
  755. <p class="graf graf--p">(3) 기록된 레퍼러를 필터로 구분하여 마케팅 채널 별 신규유입을 측정할 수 있습니다.</p>
  756. <figure class="graf graf--figure">
  757. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1600/1*T5QYPROjMq3xVWpfUYdeAQ.png?resize=1170%2C521&#038;ssl=1" alt="" width="1170" height="521" data-image-id="1*T5QYPROjMq3xVWpfUYdeAQ.png" data-width="3338" data-height="1488" data-recalc-dims="1" /><p class="wp-caption-text">콘솔에서 레퍼러로 구분된 숫자들을 확인할 수 있습니다.</p></div></figure>
  758. <h3 class="graf graf--h4">하지만…</h3>
  759. <p class="graf graf--p">하지만 우리는 단순 다운로드를 넘어 가입, 결제 등의 행동까지 유도하고, 앱 내에서 행동을 수행한 숫자를 알고 싶습니다. 하지만 이것은 위 스토어 레퍼러로는 불가능합니다. 레퍼러 값이 스토어까지는 유지되지만 앱을 다운로드 받고 진입한 후에는 사라지기 때문입니다. 행동을 측정하기 위해서는 레퍼러 구분값이 앱에 들어와서도 유지되어야 합니다. 이것은 어떻게 구현할까요?</p>
  760. <figure class="graf graf--figure">
  761. <p><div style="width: 360px" class="wp-caption aligncenter"><img class="graf-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*YyciMtfkausaCgncrEBnaA.png?resize=350%2C443&#038;ssl=1" alt="" width="350" height="443" data-image-id="1*YyciMtfkausaCgncrEBnaA.png" data-width="350" data-height="443" data-recalc-dims="1" /><p class="wp-caption-text">우리는 앱에 들어온 후에도 특정 행동을 유도하고, Step에 따라 측정하고 싶습니다.</p></div></figure>
  762. <h3 class="graf graf--h4">Deeplink로 앱 진입을 유도하자</h3>
  763. <p class="graf graf--p">행동을 유도하기 위해서는 스토어로만 보내는 링크보다는 Deeplink가 필요합니다. Deeplink는 앱이 설치되어 있다면 앱을, 없다면 Failover가 동작하는 링크입니다. Failover는 보통 스토어를 열어줍니다. Deeplink로 자연스럽게 행동을 위한 앱 진입을 유도할 수 있습니다. 하지만 Deeplink 또한 레퍼러 값이 앱에 진입하면 소실됩니다.</p>
  764. <figure class="graf graf--figure"><img class="graf-image aligncenter" src="https://i1.wp.com/cdn-images-1.medium.com/max/1600/1*YwmqEKXCDKgpp2XtnmLFfQ.png?resize=700%2C300&#038;ssl=1" data-image-id="1*YwmqEKXCDKgpp2XtnmLFfQ.png" data-width="700" data-height="300" data-recalc-dims="1" /></figure>
  765. <h3 class="graf graf--h4">Deferred Deeplink로 레퍼러를 유지하자</h3>
  766. <p class="graf graf--p">Deferred Deeplink는 기본적으로 Deeplink와 똑같이 동작하지만 링크 속성이 앱에 들어와서도 유지됩니다. 어떤 마케팅 캠페인으로부터 왔는지 구분할 수 있기 때문에 행동을 직접 유도하고, 실제로 도달하였는지 측정할 수 있습니다.</p>
  767. <figure class="graf graf--figure">
  768. <p><div style="width: 874px" class="wp-caption aligncenter"><img class="graf-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1600/1*ZnZyXEDotV04II1lOpndsw.jpeg?resize=864%2C500&#038;ssl=1" alt="" width="864" height="500" data-image-id="1*ZnZyXEDotV04II1lOpndsw.jpeg" data-width="864" data-height="500" data-recalc-dims="1" /><p class="wp-caption-text">Deeplink는 단순히 앱에 진입시키지만, Deferred Deeplink는 유지되는 레퍼러 값을 이용하여 행동을 유도할 수 있습니다.</p></div></figure>
  769. <h3 class="graf graf--h4">Deferred Deeplink를 어떻게 구현하지?</h3>
  770. <p class="graf graf--p">Deferred Deeplink를 이용하면 우리가 원하는 행동 유도 및 분석이 가능함을 알아보았습니다. 그렇다면 Deferred Deeplink는 어떻게 구현할까요? Firebase DynamicLink 등 다양한 라이브러리가 있지만 저는 Fabric의 Branch를 소개하려고 합니다. (이 시점에는 Fabric이 Twitter 소속이였는데 지금은 Firebase와 같은 Google 소속이네요!)</p>
  771. <figure class="graf graf--figure"><img class="graf-image aligncenter" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*izJL3ZCJvoa7dWWJsQakRA.png?resize=1170%2C878&#038;ssl=1" data-image-id="1*izJL3ZCJvoa7dWWJsQakRA.png" data-width="1200" data-height="900" data-is-featured="true" data-recalc-dims="1" /></figure>
  772. <h3 class="graf graf--h3"></h3>
  773. <h1 class="graf graf--h3">Branch 사용하기</h1>
  774. <p class="graf graf--p">Branch는 대시보드에서 대부분의 작업을 할 수 있습니다. 대시보드를 활용하여 Branch를 사용하는 것을 하나씩 살펴보겠습니다.</p>
  775. <h3 class="graf graf--h4">(1) 대시보드 메인화면</h3>
  776. <p class="graf graf--p">대시보드에서 링크 생성, 설정 그리고 분석까지 모두 할 수 있습니다. 메인화면에 각 기능으로 이어지는 메뉴들이 있습니다.</p>
  777. <figure class="graf graf--figure">
  778. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*wdlL7Tew_t5xAHwSW711JA.png?resize=1170%2C543&#038;ssl=1" alt="" width="1170" height="543" data-image-id="1*wdlL7Tew_t5xAHwSW711JA.png" data-width="2856" data-height="1326" data-recalc-dims="1" /><p class="wp-caption-text">Create Link, Link Settings, Sources 등의 메뉴에서 생성, 설정, 분석을 할 수 있습니다.</p></div></figure>
  779. <h3 class="graf graf--h4">(2) 링크 생성</h3>
  780. <p class="graf graf--p">Create Link 기능으로 링크를 생성할 때 Deeplink Path, Failover link, Custom Tag, OG title 등의 설정을 함께 할 수 있습니다.</p>
  781. <figure class="graf graf--figure">
  782. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*up8O8vrYLpKDbRusTZjBFQ.png?resize=1170%2C479&#038;ssl=1" alt="" width="1170" height="479" data-image-id="1*up8O8vrYLpKDbRusTZjBFQ.png" data-width="2410" data-height="988" data-recalc-dims="1" /><p class="wp-caption-text">링크를 생성 할 때 기본적인 설정을 함께 할 수 있습니다.</p></div></figure>
  783. <h3 class="graf graf--h4">(3) 링크 설정</h3>
  784. <p class="graf graf--p">Link Settings 메뉴에서 생성할 링크의 기본 설정을 정의할 수 있습니다.</p>
  785. <figure class="graf graf--figure">
  786. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1600/1*fFUnA0zWI58cg9HHYg8EwQ.png?resize=1170%2C500&#038;ssl=1" alt="" width="1170" height="500" data-image-id="1*fFUnA0zWI58cg9HHYg8EwQ.png" data-width="2360" data-height="1010" data-recalc-dims="1" /><p class="wp-caption-text">Deeplink Path의 Scheme, Failover URL 등을 정의할 수 있습니다.</p></div></figure>
  787. <h3 class="graf graf--h4">(4) 데이터 분석</h3>
  788. <p class="graf graf--p">Sources 메뉴에서 사용자들이 Deeplink를 이용한 데이터를 분석할 수 있습니다. 링크를 생성할 때 설정한 Custom Tag까지 측정이 가능합니다. 여기서 Custom Tag는 우리가 유도하려는 행동을 의미할 것입니다. 아래 그림에서는 SIGNUP 이라는 Tag가 있습니다.</p>
  789. <figure class="graf graf--figure">
  790. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*F0mdjxZwcmu6FKlujtRpTA.png?resize=1170%2C421&#038;ssl=1" alt="" width="1170" height="421" data-image-id="1*F0mdjxZwcmu6FKlujtRpTA.png" data-width="2400" data-height="864" data-recalc-dims="1" /><p class="wp-caption-text">단계별 수치 및 Custom Tag가 불린 수치까지 한눈에 볼 수 있습니다. 필터 또한 제공됩니다.</p></div></figure>
  791. <p class="graf graf--p">하지만 Deeplink는 어떤 행동이 일어났는지를 스스로 알 수 없습니다. Custom Tag 수치를 측정하기 위해서는 앱에서 넘어온 링크 데이터로 시점을 판단하고, 적절한 시점에서 행동이 일어났을 때 Custom Tag에 해당하는 이밴트를 호출해주어야 합니다. 그러면 먼저 시점을 판단하기 위한 Deferred Link 데이터를 받는 방법을 알아보겠습니다.</p>
  792. <h1 class="graf graf--h3">Deferred Link에서 데이터 받아오기</h1>
  793. <p class="graf graf--p">Branch SDK를 이용해 Intent로 넘어오는 Deferred Link 데이터를 Json 형태로 넘겨받습니다. initSession() 메소드에 콜백을 등록해 받을 수 있습니다.</p>
  794. <p></p><pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {
  795.    @Override
  796.    protected void onNewIntent(Intent intent) {
  797.        super.onNewIntent(intent);
  798.        // Intent로 넘어오는 Deferred Deeplink를 받기위해 호출합니다.
  799.        setIntent(intent);
  800.    }
  801.    @Override
  802.    protected void onStart() {
  803.        super.onStart();
  804.        // onNewIntent()가 호출된 후 Branch Session을 초기화 합니다.
  805.        initializeBranch();
  806.    }
  807. }
  808.  
  809. private void initializeBranch() {
  810.    Branch branch = Branch.getInstance(this);
  811.    branch.initSession(new Branch.BranchReferralInitListener() {
  812.        @Override
  813.        public void onInitFinished(JSONObject referringParams, BranchError error) {
  814.            if (error != null) return;
  815.            // Parse and Deep Link Parameters from referringParams
  816.        }
  817.    });
  818. }</pre><p></p>
  819. <p class="graf graf--p">Json 형태로 넘어오는 Deferred Deeplink 데이터를 파싱하면 앱 세션이 어디에서 왔는지를 구분할 수 있습니다. 이제 이밴트를 보내야 합니다.</p>
  820. <p></p><pre class="crayon-plain-tag">Branch branch = Branch.getInstance(this);
  821. branch.userCompletedAction(&quot;sign_up&quot;);</pre><p></p>
  822. <p class="graf graf--p">userCompletedAction()를 Tag와 함께 호출하면 이밴트를 보낼 수 있습니다. 성공적으로 userCompletedAction()가 호출되면 대시보드에서 Tag에 해당하는 수치가 올라갑니다.</p>
  823. <h3 class="graf graf--h4">(부록) 앱에서 Deferred Link 만들기</h3>
  824. <p class="graf graf--p">추천하기 등의 기능은 앱에서 마케팅 링크를 생성해 공유할 수 있어야 합니다. Branch는 앱에서도 Deferred Link를 만들 수 있도록 SDK를 제공합니다.</p>
  825. <p></p><pre class="crayon-plain-tag">public void createDeferredDeepLinkWithBranch() {
  826.    BranchUniversalObject branchUniversalObject = new BranchUniversalObject();
  827.    LinkProperties linkProperties = new LinkProperties();
  828.  
  829.    // 링크 속성 설정
  830.    linkProperties.setChannel("facebook");
  831.    linkProperties.setFeature("invite");
  832.    linkProperties.setCampaign("teambook");
  833.    linkProperties.addTag("inapp");
  834.  
  835.    linkProperties.addControlParameter("$og_title", "리멤버 팀 명함첩에 초대합니다.");
  836.    linkProperties.addControlParameter("$og_description", "어서오세요.");
  837.  
  838.    // 링크 생성
  839.    branchUniversalObject.generateShortUrl(this, linkProperties, new BranchLinkCreateListener() {
  840.        @Override
  841.        public void onLinkCreate(String url, BranchError error) {
  842.            if (error != null) return;
  843.            // Share url to marketing channel
  844.        }
  845.    });
  846. }</pre><p></p>
  847. <p class="graf graf--p">LinkProperties 객체에 속성을 설정하고, generateShortUrl() 메소드로 대시보드에서 만드는 것과 같은 Deferred Deeplink를 생성할 수 있습니다. 만들어진 링크의 활용, 분석은 위에서 설명한 것과 같습니다.</p>
  848. <h1 class="graf graf--h3">Branch Deferred Deeplink 활용 Flow</h1>
  849. <p class="graf graf--p">지금까지 설명드린 링크 생성, 활용, 분석은 다음 그림 하나로 요약할 수 있습니다.</p>
  850. <figure class="graf graf--figure">
  851. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="graf-image" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*s59uah-bTGANSOPo3rrdQA.png?resize=1170%2C442&#038;ssl=1" alt="" width="1170" height="442" data-image-id="1*s59uah-bTGANSOPo3rrdQA.png" data-width="1696" data-height="642" data-recalc-dims="1" /><p class="wp-caption-text">단계별 도달율이 대시보드에 모두 기록됩니다.</p></div></figure>
  852. <h1 class="graf graf--h3">마무리</h1>
  853. <p class="graf graf--p">저는 다음과 같은 순서로 Branch를 성공적으로 도입하였습니다.</p>
  854. <p class="graf graf--p">(1) 측정하고 싶은 데이터 결정 — 마케팅 채널 별로 가입자 수를 알고 싶다.</p>
  855. <p class="graf graf--p">(2) 측정 방법 조사 — Deferred Deeplink가 필요하다.</p>
  856. <p class="graf graf--p">(3) 측정 수단 결정, 적용 및 분석 — Fabric Branch 적용</p>
  857. <p class="graf graf--p">Branch 자체를 이해하는 것도 좋지만, 더 중요한 것은 데이터의 중요성을 이해하고 적설한 수단을 찾아 적용하려는 마음가짐이라고 생각합니다. Branch 보다 좋은 방법도 분명히 많이 있을 것입니다. 각자 상황에 맞는 수단을 찾아 원하는 데이터를 반드시 측정하며 좋은 서비스를 만들어가시기를 바랍니다.</p>
  858. <blockquote>
  859. <p class="graf graf--p">이 글은 미디엄에 쓴 포스팅을 옮겨왔습니다. <a href="http://bit.ly/2HMW4hE">http://bit.ly/2usHPvs</a></p>
  860. </blockquote>
  861. </div>
  862. </div>
  863. </section>
  864. <section class="section section--body">
  865. <div class="section-content"></div>
  866. </section>
  867. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2018/04/fabric-branch%eb%a1%9c-%ec%82%ac%ec%9a%a9%ec%9e%90-%ed%96%89%eb%8f%99-%eb%b6%84%ec%84%9d%ed%95%98%ea%b8%b0/">Fabric Branch로 사용자 행동 분석하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  868. ]]></content:encoded>
  869. <wfw:commentRss>https://blog.dramancompany.com/2018/04/fabric-branch%eb%a1%9c-%ec%82%ac%ec%9a%a9%ec%9e%90-%ed%96%89%eb%8f%99-%eb%b6%84%ec%84%9d%ed%95%98%ea%b8%b0/feed/</wfw:commentRss>
  870. <slash:comments>0</slash:comments>
  871. <post-id xmlns="com-wordpress:feed-additions:1">934</post-id> </item>
  872. <item>
  873. <title>Firebase Remote Config로 배포없이 운영하기</title>
  874. <link>https://blog.dramancompany.com/2018/04/firebase-remote-config%eb%a1%9c-%eb%b0%b0%ed%8f%ac%ec%97%86%ec%9d%b4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0/</link>
  875. <comments>https://blog.dramancompany.com/2018/04/firebase-remote-config%eb%a1%9c-%eb%b0%b0%ed%8f%ac%ec%97%86%ec%9d%b4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0/#respond</comments>
  876. <pubDate>Mon, 09 Apr 2018 01:30:03 +0000</pubDate>
  877. <dc:creator><![CDATA[rfrost]]></dc:creator>
  878. <category><![CDATA[기술 블로그]]></category>
  879.  
  880. <guid isPermaLink="false">http://blog.dramancompany.com/?p=923</guid>
  881. <description><![CDATA[<p>라이브로 운영하는 서비스는 항상 운영이슈가 존재합니다. 운영이슈는 사용자의 요구를 최대한 실시간으로 대응하여 불편함을 줄이고 만족도를 높이는 것을 의미합니다. 예를 들어 CS, 공지사항 부터 장애 모니터링 및 대응, 피드백 수집 후 개선까지도 모두 운영이슈로 볼 수 있습니다. 이 때 운영팀에서 가장 중요하게 생각하는 것은 실시간 입니다. 운영팀은 공지사항, 장애 등 이슈가 있을 때 원하는 시간에 바로바로<a class="button" href="https://blog.dramancompany.com/2018/04/firebase-remote-config%eb%a1%9c-%eb%b0%b0%ed%8f%ac%ec%97%86%ec%9d%b4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0/" title="Read More">Read more</a></p>
  882. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2018/04/firebase-remote-config%eb%a1%9c-%eb%b0%b0%ed%8f%ac%ec%97%86%ec%9d%b4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0/">Firebase Remote Config로 배포없이 운영하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  883. ]]></description>
  884. <content:encoded><![CDATA[<p id="adeb" class="graf graf--p graf-after--h3">라이브로 운영하는 서비스는 항상 운영이슈가 존재합니다. 운영이슈는 사용자의 요구를 최대한 실시간으로 대응하여 불편함을 줄이고 만족도를 높이는 것을 의미합니다. 예를 들어 CS, 공지사항 부터 장애 모니터링 및 대응, 피드백 수집 후 개선까지도 모두 운영이슈로 볼 수 있습니다. 이 때 운영팀에서 가장 중요하게 생각하는 것은 실시간 입니다. 운영팀은 공지사항, 장애 등 이슈가 있을 때 원하는 시간에 바로바로 대응할 수 있는 시스템을 원합니다.</p>
  885. <p id="7364" class="graf graf--p graf-after--p">하지만 앱은 개발, 리뷰, 테스트, 스토어 업로드 등 여러 과정을 거쳐야 하므로 변경사항을 바로 반영하기가 힘듭니다. 이는 운영팀이 원하는 실시간과 거리가 멉니다. 운영팀이 원하는 것은 다음과 같습니다.</p>
  886. <ol class="postList">
  887. <li id="ce07" class="graf graf--li graf-after--p">개발자를 통하지 않고 스스로 변경 가능하다.</li>
  888. <li id="9079" class="graf graf--li graf-after--li">코드를 손대지 않고 안전하게 변경한다.</li>
  889. <li id="3389" class="graf graf--li graf-after--li">배포하지 않고 변경사항을 적용한다.</li>
  890. <li id="1895" class="graf graf--li graf-after--li">원하는 사용자에게만 변경사항을 적용한다.</li>
  891. </ol>
  892. <p id="1e47" class="graf graf--p graf-after--li">어떻게 운영팀이 원하는 이것을 이룰 수 있을까요?</p>
  893. <figure id="3aba" class="graf graf--figure graf-after--p">
  894. <div class="aspectRatioPlaceholder is-locked">
  895. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*tadpqGa9KjLphMZYo6WgRA.jpeg" data-width="1920" data-height="1080" data-is-featured="true" data-action="zoom" data-action-value="1*tadpqGa9KjLphMZYo6WgRA.jpeg" data-scroll="native">
  896. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*tadpqGa9KjLphMZYo6WgRA.jpeg?resize=1170%2C658&#038;ssl=1" alt="" width="1170" height="658" data-src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*tadpqGa9KjLphMZYo6WgRA.jpeg?resize=1170%2C658&#038;ssl=1" data-recalc-dims="1" /><p class="wp-caption-text">해답은&#8230; 리모트 컨피그</p></div></p>
  897. </div>
  898. </div>
  899. </figure>
  900. <p class="graf graf--p graf-after--figure">리모트 컨피그는 사용자가 앱 업데이트를 통하지 않고 동작을 변경할 수 있는 실시간 클라우드 서비스 입니다. 사용 시나리오는 다음과 같습니다.</p>
  901. <ol class="postList">
  902. <li id="6c24" class="graf graf--li graf-after--p">Firebase에 앱의 동작을 제어하는 값을 정의한다.</li>
  903. <li id="43e0" class="graf graf--li graf-after--li">앱에서 Firebase에 정의된 값을 가져와 적용한다.</li>
  904. <li id="bc28" class="graf graf--li graf-after--li">배포 없이 업데이트 된 새로운 동작을 확인하다.</li>
  905. </ol>
  906. <p id="8181" class="graf graf--p graf-after--li">2,3번의 작업을 미리 앱에 배포해 놓으면, 운영팀에서 1번의 작업을 통해 배포 없이 자동으로 앱 업데이트가 가능합니다. 그러면 이제 사용법을 익혀봅시다.</p>
  907. <h3 class="graf graf--p graf-after--li">1. Firebase, 리모트 컨피그 설치하기</h3>
  908. <p id="0b88" class="graf graf--p graf-after--h4">Gradle에 의존성을 정의하고, Firebase Console에서 google-services.json을 받아와 app module에 추가합니다.</p>
  909. <p></p><pre class="crayon-plain-tag">dependencies {
  910.    classpath 'com.google.gms:google-services:3.0.0'
  911. }</pre><p></p><pre class="crayon-plain-tag">dependencies {
  912.    compile 'com.google.firebase:firebase-core:10.2.0'
  913.    compile 'com.google.firebase:firebase-config:10.2.0'
  914. }
  915.  
  916. // Add this at the bottom of build.gradle in app module
  917. apply plugin: 'com.google.gms.google-services'</pre><p></p>
  918. <figure id="ea11" class="graf graf--figure graf-after--pre">
  919. <div class="aspectRatioPlaceholder is-locked">
  920. <div class="aspectRatioPlaceholder-fill">
  921. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*HwLZ93J-UwQSFGclrLbQkA.png?resize=1170%2C300&#038;ssl=1" alt="" width="1170" height="300" data-src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*HwLZ93J-UwQSFGclrLbQkA.png?resize=1170%2C300&#038;ssl=1" data-recalc-dims="1" /><p class="wp-caption-text">google-services.json을 다운로드 후 app module에 위치</p></div></p>
  922. </div>
  923. </div>
  924. </figure>
  925. <h3 id="4daa" class="graf graf--h4 graf-after--figure">2. 구글 플레이 서비스 설치 체크</h3>
  926. <p id="64f9" class="graf graf--p graf-after--h4">리모트 컨피그는 구글 플레이 서비스가 기기에 설치되어 있어야 사용 가능합니다. 앱을 시작할 때 구글 플레이 서비스 설치 여부를 확인하고, 안되어있다면 사용자에게 설치를 유도할 수 있도록 에러 팝업을 띄어줍니다.</p>
  927. <p></p><pre class="crayon-plain-tag">private void checkGooglePlayServices() {
  928.    GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
  929.    int status = googleApiAvailability.isGooglePlayServicesAvailable(context);
  930.  
  931.    if (status != ConnectionResult.SUCCESS) {
  932.        Dialog dialog = googleApiAvailability.getErrorDialog(activity, status, -1);
  933.        dialog.setOnDismissListener(dialogInterface -&gt; finish());
  934.        dialog.show();
  935.  
  936.        googleApiAvailability.showErrorNotification(context, status);
  937.    }
  938. }</pre><p>&nbsp;</p>
  939. <h3 id="6b6f" class="graf graf--h4 graf-after--pre">3. 어드민에 값 추가하기</h3>
  940. <p id="f846" class="graf graf--p graf-after--h4">이제 운영팀이 자유롭게 변경하고 싶은 값을 정의해봅시다. 값 정의는 Fireabse 콘솔에 있는 리모트 컨피그 어드민에서 가능합니다.</p>
  941. <figure id="686d" class="graf graf--figure graf-after--p">
  942. <div class="aspectRatioPlaceholder is-locked">
  943. <div class="aspectRatioPlaceholder-fill">
  944. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*Sc1x-W2LSitCNELLgqvqhQ.png?resize=1170%2C439&#038;ssl=1" alt="" width="1170" height="439" data-src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*Sc1x-W2LSitCNELLgqvqhQ.png?resize=1170%2C439&#038;ssl=1" data-recalc-dims="1" /><p class="wp-caption-text">리모트 컨피그 어드민에서 매개변수를 key, value 형태로 추가할 수 있습니다.</p></div></p>
  945. </div>
  946. </div><figcaption class="imageCaption"></figcaption><figcaption class="imageCaption">
  947. <p><div style="width: 1610px" class="wp-caption aligncenter"><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*eujrvHoc_GAhs4BFdi3J6g.png?resize=1170%2C542&#038;ssl=1" alt="" width="1170" height="542" data-src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*eujrvHoc_GAhs4BFdi3J6g.png?resize=1170%2C542&#038;ssl=1" data-recalc-dims="1" /><p class="wp-caption-text">추가된 값들은 다음과 같이 보여집니다.</p></div></p>
  948. </figcaption></figure>
  949. <h3 id="fa49" class="graf graf--h4 graf-after--figure">4. 리모트 컨피그 초기화하기</h3>
  950. <p id="b374" class="graf graf--p graf-after--h4">어드민에서 정의한 값들을 받아오기 위해 리모트 컨피그 객체를 초기화 합니다.</p>
  951. <p></p><pre class="crayon-plain-tag">public static void initialize() {
  952.    FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
  953.    FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
  954.            // Debug일 때 Developer Mode를 enable 하여 캐쉬 설정을 변경한다.
  955.            .setDeveloperModeEnabled(BuildConfig.DEBUG)
  956.            .build();
  957.  
  958.    remoteConfig.setConfigSettings(configSettings);
  959.    // 로컬 기본값을 저장한 xml을 설정한다.
  960.    remoteConfig.setDefaults(R.xml.remote_config_defaults);
  961.  
  962.    // 기본 캐쉬 만료시간은 12시간이다. Developer Mode 여부에 따라 fetch()에 적설한 캐시 만료시간을 넘긴다.
  963.    remoteConfig.fetch(0).addOnCompleteListener(task -&gt; {
  964.        if (task.isSuccessful()) remoteConfig.activateFetched();
  965.    });
  966. }</pre><p></p>
  967. <p id="5cf4" class="graf graf--p graf-after--pre">setDefaults()로 설정한 remote_config_defaults.xml 에서는 어드민에서 값을 못받아올 경우 사용할 로컬 기본값들을 정의합니다.</p>
  968. <p></p><pre class="crayon-plain-tag">&lt;?xml version="1.0" encoding="utf-8"?&gt;
  969. &lt;defaultsMap&gt;
  970. &lt;entry&gt;
  971.    &lt;key&gt;example_key&lt;/key&gt;
  972.    &lt;value&gt;example local default value&lt;/value&gt;
  973. &lt;/entry&gt;
  974. &lt;entry&gt;
  975.    &lt;key&gt;condition_example_key&lt;/key&gt;
  976.    &lt;value&gt;condition example local default value&lt;/value&gt;
  977. &lt;/entry&gt;
  978. &lt;/defaultsMap&gt;</pre><p>&nbsp;</p>
  979. <h3 class="graf graf--h4 graf-after--pre">5. 어드민에서 값 가져오기</h3>
  980. <p id="cfa5" class="graf graf--p graf-after--h4">리모트 컨피그 객체의 getString() 메소드를 활용하여 넘겨준 key의 value를 가져옵니다.</p>
  981. <p></p><pre class="crayon-plain-tag">public static String getConfigValue(String key) {
  982.    FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
  983.    return remoteConfig.getString(key);
  984. }</pre><p></p>
  985. <h3 id="9be9" class="graf graf--h3 graf-after--pre">리멤버에서의 활용 예시</h3>
  986. <p id="e5b0" class="graf graf--p graf-after--h3">현재 리멤버에서는 다음과 같은 시나리오에서 리모트 컨피그를 활용하고 있습니다.</p>
  987. <h4>1. 메인 공지사항 팝업 이미지 및 액션</h4>
  988. <figure id="37cc" class="graf graf--figure graf-after--li">
  989. <div class="aspectRatioPlaceholder is-locked">
  990. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*4Nke7QJjcHtVrY00oAhbVw.png" data-width="567" data-height="1008" data-scroll="native"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="42" height="75"></canvas><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*4Nke7QJjcHtVrY00oAhbVw.png?w=1170&#038;ssl=1" data-src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*4Nke7QJjcHtVrY00oAhbVw.png?w=1170&#038;ssl=1" data-recalc-dims="1" /></div>
  991. </div>
  992. </figure>
  993. <h4 id="b24d" class="graf graf--p graf-after--figure">2. Drawer 추천유도 텍스트</h4>
  994. <figure id="7ea8" class="graf graf--figure graf-after--p">
  995. <div class="aspectRatioPlaceholder is-locked">
  996. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*51OLlpcxdoQJPc_onVu6gQ.png" data-width="567" data-height="1008" data-scroll="native"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="42" height="75"></canvas><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*51OLlpcxdoQJPc_onVu6gQ.png?w=1170&#038;ssl=1" data-src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*51OLlpcxdoQJPc_onVu6gQ.png?w=1170&#038;ssl=1" data-recalc-dims="1" /></div>
  997. </div>
  998. </figure>
  999. <h4 id="aef8" class="graf graf--p graf-after--figure">3. 촬영 후 추천유도 텍스트, 이미지 및 액션</h4>
  1000. <figure id="df55" class="graf graf--figure graf-after--p">
  1001. <div class="aspectRatioPlaceholder is-locked">
  1002. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*woMr0GB9XjTCdekR66V3lQ.png" data-width="567" data-height="1008" data-scroll="native"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="42" height="75"></canvas><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*woMr0GB9XjTCdekR66V3lQ.png?w=1170&#038;ssl=1" data-src="https://i0.wp.com/cdn-images-1.medium.com/max/1600/1*woMr0GB9XjTCdekR66V3lQ.png?w=1170&#038;ssl=1" data-recalc-dims="1" /></div>
  1003. </div>
  1004. </figure>
  1005. <h4 id="b1ef" class="graf graf--p graf-after--figure">4. FAB 가이드 이미지 및 액션</h4>
  1006. <figure id="9176" class="graf graf--figure graf-after--p">
  1007. <div class="aspectRatioPlaceholder is-locked">
  1008. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*AUIopIeFfevdP0Px7YrpFw.png" data-width="567" data-height="1008" data-scroll="native"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="42" height="75"></canvas><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*AUIopIeFfevdP0Px7YrpFw.png?w=1170&#038;ssl=1" data-src="https://i2.wp.com/cdn-images-1.medium.com/max/1600/1*AUIopIeFfevdP0Px7YrpFw.png?w=1170&#038;ssl=1" data-recalc-dims="1" /></div>
  1009. </div>
  1010. </figure>
  1011. <h4 id="6cab" class="graf graf--p graf-after--figure">5. 대기명함 가이드 텍스트</h4>
  1012. <div class="section-inner sectionLayout--outsetRow" data-paragraph-count="2">
  1013. <figure id="8e34" class="graf graf--figure graf--layoutOutsetRow is-partialWidth graf-after--p" data-scroll="native">
  1014. <div class="aspectRatioPlaceholder is-locked">
  1015. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*MF3mZlOk0oOnyPjK6RWfYw.png" data-width="566" data-height="544" data-action="zoom" data-action-value="1*MF3mZlOk0oOnyPjK6RWfYw.png" data-scroll="native"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="75" height="71"></canvas><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1200/1*MF3mZlOk0oOnyPjK6RWfYw.png?w=1170&#038;ssl=1" data-src="https://i1.wp.com/cdn-images-1.medium.com/max/1200/1*MF3mZlOk0oOnyPjK6RWfYw.png?w=1170&#038;ssl=1" data-recalc-dims="1" /></div>
  1016. </div>
  1017. </figure>
  1018. <figure id="49db" class="graf graf--figure graf--layoutOutsetRowContinue is-partialWidth graf-after--figure" data-scroll="native">
  1019. <div class="aspectRatioPlaceholder is-locked">
  1020. <div class="aspectRatioPlaceholder-fill"></div>
  1021. <div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*zeFioOHYR16x_LutWWkWqQ.png" data-width="567" data-height="424" data-action="zoom" data-action-value="1*zeFioOHYR16x_LutWWkWqQ.png" data-scroll="native"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="75" height="55"></canvas><img class="progressiveMedia-image js-progressiveMedia-image" src="https://i1.wp.com/cdn-images-1.medium.com/max/1200/1*zeFioOHYR16x_LutWWkWqQ.png?w=1170&#038;ssl=1" data-src="https://i1.wp.com/cdn-images-1.medium.com/max/1200/1*zeFioOHYR16x_LutWWkWqQ.png?w=1170&#038;ssl=1" data-recalc-dims="1" /></div>
  1022. </div>
  1023. </figure>
  1024. </div>
  1025. <div class="section-inner sectionLayout--insetColumn">
  1026. <h3 class="graf graf--h3 graf-after--figure"></h3>
  1027. <h3 id="d8d4" class="graf graf--h3 graf-after--figure">리모트 컨피그의 장점</h3>
  1028. <h4 id="468b" class="graf graf--h4 graf-after--h3">1. 실시간 운영변수 변경 시스템 구축이 쉽다.</h4>
  1029. <p id="7e04" class="graf graf--p graf-after--h4">보통 라이브로 운영하는 서비스는 이러한 실시간 운영변수 변경 시스템을 직접 구축하여 사용합니다. 리멤버 또한 리모트 컨피그를 사용하기 전까지는 자체 시스템이 있었습니다. 하지만 직접 구현하는 것은 많은 리소스가 필요합니다. 리모트 컨피그를 사용하면 이런 시스템을 쉽게 갖출 수 있습니다.</p>
  1030. <h4 id="a536" class="graf graf--h4 graf-after--p">2. 값을 단순히 변경하는 것 뿐만 아니라 대상을 선택하여 배포할 수 있다.</h4>
  1031. <p id="1425" class="graf graf--p graf-after--h4">사용자 또는 기기 속성에 따라 값을 분기하여 배포하는 것은 유용한 기능이지만 개발하려면 손이 많이 가는 일입니다. 리모트 컨피그를 사용하면 쉽게 대상을 선택하여 배포할 수 있습니다.</p>
  1032. <h3 class="graf graf--h3 graf-after--p"></h3>
  1033. <h3 id="a679" class="graf graf--h3 graf-after--p">마무리</h3>
  1034. <p id="7ecc" class="graf graf--p graf-after--h3 graf--trailing">리모트 컨피그는 라이브 서비스에게 매우 중요한 기능을 쉽고 빠르게 적용할 수 있도록 돕습니다. 저는 Firebase에서 가장 가성비가 좋은 기능이 리모트 컨피그가 아닌가 생각합니다. 이제 리모트 컨피그로 운영팀의 걱정을 덜어주세요.</p>
  1035. <p class="graf graf--p graf-after--h3 graf--trailing">
  1036. </div>
  1037. <blockquote id="8381" class="graf graf--blockquote graf--leading"><p>&#8211; 이 글에 첨부된 코드는 <a class="markup--anchor markup--blockquote-anchor" href="https://github.com/rfrost77/DroidKnights-RemoteConfig" target="_blank" rel="nofollow noopener noreferrer" data-href="https://github.com/rfrost77/DroidKnights-RemoteConfig">https://github.com/rfrost77/DroidKnights-RemoteConfig</a> 에 있습니다.</p></blockquote>
  1038. <blockquote id="9418" class="graf graf--blockquote graf-after--blockquote graf--trailing"><p>&#8211; 이 글은 미디엄에 쓴 포스팅을 옮겨왔습니다. <a href="http://bit.ly/2usHPvs">http://bit.ly/2usHPvs</a></p></blockquote>
  1039. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2018/04/firebase-remote-config%eb%a1%9c-%eb%b0%b0%ed%8f%ac%ec%97%86%ec%9d%b4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0/">Firebase Remote Config로 배포없이 운영하기</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1040. ]]></content:encoded>
  1041. <wfw:commentRss>https://blog.dramancompany.com/2018/04/firebase-remote-config%eb%a1%9c-%eb%b0%b0%ed%8f%ac%ec%97%86%ec%9d%b4-%ec%9a%b4%ec%98%81%ed%95%98%ea%b8%b0/feed/</wfw:commentRss>
  1042. <slash:comments>0</slash:comments>
  1043. <post-id xmlns="com-wordpress:feed-additions:1">923</post-id> </item>
  1044. <item>
  1045. <title>빅데이터 프레임워크를 활용한 데이터 인프라 구축</title>
  1046. <link>https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/</link>
  1047. <comments>https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/#comments</comments>
  1048. <pubDate>Tue, 29 Aug 2017 06:16:16 +0000</pubDate>
  1049. <dc:creator><![CDATA[김 종옥]]></dc:creator>
  1050. <category><![CDATA[기술 블로그]]></category>
  1051. <category><![CDATA[airflow]]></category>
  1052. <category><![CDATA[hadoop]]></category>
  1053. <category><![CDATA[presto]]></category>
  1054. <category><![CDATA[spark]]></category>
  1055. <category><![CDATA[superset]]></category>
  1056. <category><![CDATA[zeppelin]]></category>
  1057.  
  1058. <guid isPermaLink="false">http://blog.dramancompany.com/?p=826</guid>
  1059. <description><![CDATA[<p>빅데이터 분석을 위한 인프라 구축에 대한 경험을 공유하고자 합니다. 최근 데이터 분석을 위한 데이터 처리 시간의 증가로 기존 데이터 처리방법의 한계를 경험하였습니다. 결국 빅데이터 프레임워크를 검토하고 최종적으로 기술을 선정하여 도입하게 되었습니다. 이 과정에서의 경험이 비슷한 고민을 하는 사람들에게도 도움이 될 것으로 여겨 글을 작성하고 공유하게 되었습니다. &#160; 많은 회사에서 그렇듯이 데이터를 기반으로 현재 서비스의 현황을<a class="button" href="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/" title="Read More">Read more</a></p>
  1060. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/">빅데이터 프레임워크를 활용한 데이터 인프라 구축</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1061. ]]></description>
  1062. <content:encoded><![CDATA[<p>빅데이터 분석을 위한 인프라 구축에 대한 경험을 공유하고자 합니다. 최근 데이터 분석을 위한 데이터 처리 시간의 증가로 기존 데이터 처리방법의 한계를 경험하였습니다. 결국 빅데이터 프레임워크를 검토하고 최종적으로 기술을 선정하여 도입하게 되었습니다. 이 과정에서의 경험이 비슷한 고민을 하는 사람들에게도 도움이 될 것으로 여겨 글을 작성하고 공유하게 되었습니다.</p>
  1063. <p>&nbsp;</p>
  1064. <p>많은 회사에서 그렇듯이 데이터를 기반으로 현재 서비스의 현황을 정확하게 파악하고 합리적인 의사결정을 할 수 있도록 여러 지표를 만들고 이를 정기적으로 모니터링 합니다. 때에 따라서는 가설을 세우고 이를 확인하기 위해 데이터를 이용하여 분석을 합니다. 가설을 세우고 데이터를 만들어 분석하는 전담 부서를 두기도 하지만 업무에 대한 지식과 관련 데이터는 업무 담당자가 가장 잘 알 수 있는 부분이므로 데이터를 분석하는 것은 모두에게 필요한 부분이라 생각합니다.</p>
  1065. <p>&nbsp;</p>
  1066. <p>하지만 전체 데이터의 구조나 관련 기술이 부족한 업무 담당자가 분석을 위한 데이터를 처음부터 찾아서 보는 것은 매우 어려운 작업입니다.</p>
  1067. <p>&nbsp;</p>
  1068. <p>저는 이러한 사람들이 좀 더 쉽게 데이터를 통해 원하는 분석 결과를 얻을 수 있도록 데이터 추출과 분석을 지원하는 업무를 하고 있습니다. 사내에서는 이를 &#8216;Data Intelligence&#8217;라고 부르고 있으며, 타 팀에서 데이터를 효과적으로 분석할 수 있도록 저장된 데이터를 가공하여 추출하며, 경우에 따라서는 데이터를 수집하는 업무를 하고 있습니다.</p>
  1069. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?ssl=1"><img data-attachment-id="877" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/a2/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?fit=1113%2C626&amp;ssl=1" data-orig-size="1113,626" 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="a2" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?resize=449%2C304&amp;ssl=1" class="wp-image-877 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?resize=648%2C365&#038;ssl=1" alt="" width="648" height="365" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?w=1113&amp;ssl=1 1113w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a2.png?resize=768%2C432&amp;ssl=1 768w" sizes="(max-width: 648px) 100vw, 648px" data-recalc-dims="1" /></a></p>
  1070. <p>&nbsp;</p>
  1071. <h3><strong>무엇이 문제인가?</strong></h3>
  1072. <p>데이터 사이즈의 크기가 늘어나면서 더 높은 처리 속도가 필요하였고, API 로그 등의 데이터를 DB 데이터와 연동해서 봐야하는 Needs가 증가했습니다.</p>
  1073. <p>&nbsp;</p>
  1074. <p>데이터 추출 작업을 생각해보면, 데이터가 DB 테이블에 저장 되었을 경우 간단히 SQL 쿼리를 통해 원하는 데이터를 찾을 수 있습니다. 이 경우 데이터 기준을 요청자와 논의하면서 적절한 쿼리를 작성 후 엑셀로 추출하여 요청자에게 전달하게 됩니다. 이때 데이터 조회 속도가 너무 오래 걸린다면 날짜와 같은 키로 쿼리로 나누어서 조회하기도 하고 인덱스 등을 조정하기도 합니다.</p>
  1075. <p>&nbsp;</p>
  1076. <p>만약 데이터 추출이 쿼리로 불가능하거나 처리 속도를 높일 필요가 있을 경우 Python, Java 등의 언어로 프로그램을 만들어 추출하기도 합니다. 때에 따라서는 중복된 데이터 처리를 피하기 위해 중간 과정의 데이터를 만들어 활용하기도 하며, 서버 사양을 높이거나 병렬 처리를 통해 최종 데이터 생성의 속도를 높이는 시도를 하기도 합니다.</p>
  1077. <p>&nbsp;</p>
  1078. <p>많은 노력에도 불구하고 어떤 데이터의 경우는 이틀 이상 소요되는 경우가 많아 졌습니다.</p>
  1079. <p>&nbsp;</p>
  1080. <p>또한 API로그를 통해서만 볼 수 있는 분석에 대한 요청도 있었습니다. 앱에서 버그가 발생하여 동일 API가 여러 번 호출 되는 경우가 있었는데 이 버그의 영향이 어느 정도 영향을 미쳤는지 파악하기 위해 API 로그를 살펴보아야 했습니다. 이러한 케이스의 로그 데이터 분석은  <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/">ELK</a>, AWS Cloud Watch에서는 살펴보기에는 어려움이 있었습니다.</p>
  1081. <p>&nbsp;</p>
  1082. <p>이러한 과거 데이터 처리, 추출 방식의 한계와 향후 더 원할한 분석을 위해 빅데이터 분석을 위한 인프라 구축을 고려하게 되었습니다.</p>
  1083. <p>&nbsp;</p>
  1084. <h3><strong>우리에게 필요한 것은 무엇인가?</strong></h3>
  1085. <p>가장 먼저 선행 했던 업무는 요구사항을 명확히 이해하는 것부터 시작하였습니다.</p>
  1086. <p>데이터를 자주 보는 업무 담당자들과의 인터뷰를 통해 현재 데이터 추출에서의 어려움 등을 듣고 향후 변경될 경우 어떤 기능이 필요한지에 대한 이야기를 들었습니다. 이를 통해 기능적 관점의 요구사항을 도출 하였습니다. 한편으로는 데이터 추출, 분석을 지원하는 입장에서의 기술적 요구사항을 정리해 보았습니다.</p>
  1087. <p>이러한 모든 요구사항을 취합하여 기술적 관점과 기능적 관점을 구분하여 정리하였습니다. 현재 현황이 어떠한지 요구사항별 중요도는 어떠한지 등을 파악해보았습니다.</p>
  1088. <p>&nbsp;</p>
  1089. <p><strong>기능적 관점에서의 요구사항</strong></p>
  1090. <table>
  1091. <tbody>
  1092. <tr>
  1093. <td><strong>구분</strong></td>
  1094. <td><strong>요구사항</strong></td>
  1095. <td><strong>우선순위</strong></td>
  1096. <td><strong>As-Is</strong></td>
  1097. <td><strong>To-Be</strong></td>
  1098. </tr>
  1099. <tr>
  1100. <td>데이터 연결</td>
  1101. <td>다양한 정형/ 비정형 데이터를 연결해서 볼 수 있어야 한다</p>
  1102. <p>날짜에 별도 Annotation을 달 수 있어야 한다</td>
  1103. <td style="text-align: center;">B</td>
  1104. <td style="text-align: center;">X</td>
  1105. <td style="text-align: center;">O</td>
  1106. </tr>
  1107. <tr>
  1108. <td>데이터 가공/</p>
  1109. <p>추출</td>
  1110. <td>비 개발자도 손쉽게 데이터를 가공/ 추출 할 수 있어야 한다</p>
  1111. <ul>
  1112. <li>데이터의 중간 단계별 가공(예: 피벗)이 쉬워야 한다</li>
  1113. <li>동일 쿼리에 대해 변수값을 바꿔가며 돌릴 수 있어야 한다</li>
  1114. </ul>
  1115. </td>
  1116. <td style="text-align: center;">A</td>
  1117. <td style="text-align: center;">▵</td>
  1118. <td style="text-align: center;">O</td>
  1119. </tr>
  1120. <tr>
  1121. <td>Export</td>
  1122. <td>CSV와 같은 형식의 파일로 데이터를 추출 할 수 있어야 한다</td>
  1123. <td style="text-align: center;">B</td>
  1124. <td style="text-align: center;">O</td>
  1125. <td style="text-align: center;">O</td>
  1126. </tr>
  1127. <tr>
  1128. <td>데이터 공유</td>
  1129. <td>다른 사람이 작성한 추출 로직을 쉽게 공유할 수 있어야 한다</td>
  1130. <td style="text-align: center;">B</td>
  1131. <td style="text-align: center;">▵</td>
  1132. <td style="text-align: center;">O</td>
  1133. </tr>
  1134. <tr>
  1135. <td>데이터 시각화</td>
  1136. <td>다양한 그래프(히스토그램, 코호트 차트 등), 차트 등을 지원해야 한다</td>
  1137. <td style="text-align: center;">A</td>
  1138. <td style="text-align: center;">▵</td>
  1139. <td style="text-align: center;">O</td>
  1140. </tr>
  1141. <tr>
  1142. <td>알림</td>
  1143. <td>미리 정의한 알림을 메일, 슬랙 등 다양한 채널로 받을 수 있어야 한다</p>
  1144. <p>알림 조건을 쉽게 설정할 수 있어야 한다</p>
  1145. <ul>
  1146. <li>특정 데이터의 증감이 있는 경우</li>
  1147. <li>클릭, 노출 등에 관한 지표의 이상 변화 감지</li>
  1148. </ul>
  1149. </td>
  1150. <td style="text-align: center;">A</td>
  1151. <td style="text-align: center;">▵</td>
  1152. <td style="text-align: center;">O</td>
  1153. </tr>
  1154. </tbody>
  1155. </table>
  1156. <p>&nbsp;</p>
  1157. <p><strong>기술적 관점에서의 요구사항</strong></p>
  1158. <table style="height: 148px; width: 715px;">
  1159. <tbody>
  1160. <tr>
  1161. <td style="width: 114px; text-align: center;"><strong>구분</strong></td>
  1162. <td style="width: 411px; text-align: center;"><strong>요구사항</strong></td>
  1163. <td style="width: 87px; text-align: center;"><strong>우선순위</strong></td>
  1164. <td style="width: 70px; text-align: center;"><strong>As-Is</strong></td>
  1165. <td style="width: 85px; text-align: center;"><strong>To-Be</strong></td>
  1166. </tr>
  1167. <tr>
  1168. <td style="width: 114px;">추출 속도</td>
  1169. <td style="width: 411px;">데이터 추출 시간이 빨라야 한다</td>
  1170. <td style="width: 87px; text-align: center;">A</td>
  1171. <td style="width: 70px; text-align: center;">▵</td>
  1172. <td style="width: 85px; text-align: center;">O</td>
  1173. </tr>
  1174. <tr>
  1175. <td style="width: 114px;">보안</td>
  1176. <td style="width: 411px;">테이블 구조와 원본 데이터가 데이터를 직접 추출하는 사람들에게 노출되지 않아야 한다</td>
  1177. <td style="width: 87px; text-align: center;">A</td>
  1178. <td style="width: 70px; text-align: center;">O</td>
  1179. <td style="width: 85px; text-align: center;">O</td>
  1180. </tr>
  1181. <tr>
  1182. <td style="width: 114px;">비용</td>
  1183. <td style="width: 411px;">데이터 추출 비용을 최소화 해야 한다</td>
  1184. <td style="width: 87px; text-align: center;">B</td>
  1185. <td style="width: 70px; text-align: center;">▵</td>
  1186. <td style="width: 85px; text-align: center;">▵</td>
  1187. </tr>
  1188. <tr>
  1189. <td style="width: 114px;">개발 생산성</td>
  1190. <td style="width: 411px;">개발 생산성이 좋아야 한다</p>
  1191. <ul>
  1192. <li>추출 프로그램 작성이 쉬워야 한다</li>
  1193. <li>추출 인프라 구성이 쉬워야 한다</li>
  1194. </ul>
  1195. </td>
  1196. <td style="width: 87px; text-align: center;">A</td>
  1197. <td style="width: 70px; text-align: center;">▵</td>
  1198. <td style="width: 85px; text-align: center;">O</td>
  1199. </tr>
  1200. <tr>
  1201. <td style="width: 114px;">장애 내구성/</p>
  1202. <p>안정성</td>
  1203. <td style="width: 411px;">장애가 발생할 경우 바로 인지 할 수 있어야 한다</p>
  1204. <p>장애 발생시 최대한 빠르게/ 자동으로 복구 되어야 한다</td>
  1205. <td style="width: 87px; text-align: center;">A</td>
  1206. <td style="width: 70px; text-align: center;">▵</td>
  1207. <td style="width: 85px; text-align: center;">O</td>
  1208. </tr>
  1209. <tr>
  1210. <td style="width: 114px;">확장성(Scalability)</td>
  1211. <td style="width: 411px;">확장성 있는 구조 설계가 되어야 한다</td>
  1212. <td style="width: 87px; text-align: center;">C</td>
  1213. <td style="width: 70px; text-align: center;">X</td>
  1214. <td style="width: 85px; text-align: center;">O</td>
  1215. </tr>
  1216. </tbody>
  1217. </table>
  1218. <p>&nbsp;</p>
  1219. <p>요구 사항 분석을 통해 향후 데이터 추출을 위한 빅데이터 인프라의 모습을 대략적으로 생각해 볼 수 있었습니다.</p>
  1220. <p><strong> </strong></p>
  1221. <h3><strong>Hadoop? Spark?</strong></h3>
  1222. <p><a href="http://hadoop.apache.org/">아파치 하둡 플랫폼(Hadoop)</a>은 막대한 볼륨의 데이터를 저장할 수 있는 구글 파일 시스템과 이러한 데이터를 빠르고 안정적으로 처리할 수 있는 <a href="https://static.googleusercontent.com/media/research.google.com/ko//archive/mapreduce-osdi04.pdf">구글 맵리듀스(Google MapReduce) </a>기술의 오픈소스 버전이라고 할 수 있습니다. 많은 기업들이 빠르게 증가하는 데이터(구조적, 반구조적, 비구조적)를 관리하기 위해 하둡을 채택하였습니다.</p>
  1223. <p>적은 비용으로 페타바이트 급의 데이터를 안정적으로 처리할 수 있음이 입증 되면서 빅테이터를 위한 범용 저장소 및 분석 플랫폼으로서 업계의 인정을 받았습니다. (<a href="https://en.wikipedia.org/wiki/Apache_Hadoop">2009년 4월 야후는 하둡으로 1테라바이트를 62초에 정렬하였음을 발표</a>)</p>
  1224. <p>&nbsp;</p>
  1225. <p>아파치 하둡 프로젝트 자체는 데이터를 분산하여 저장할 수 있는 파일시스템인 HDFS와 데이터를 분산하여 처리하는 맵리듀스(MapReduce)만을 포함합니다. 이는 빅데이터를 분석하기 위한 모든 범주를 포함하지 않으므로 이를 보완하기 위한 프로젝트들이 생기면서 하둡 생태계(Hadoop Ecosystem)가 이루어지게 되었습니다.</p>
  1226. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/hadoop-ecosystem.png?ssl=1"><img data-attachment-id="844" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/hadoop-ecosystem/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/hadoop-ecosystem.png?fit=640%2C360&amp;ssl=1" data-orig-size="640,360" 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="hadoop-ecosystem" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/hadoop-ecosystem.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/hadoop-ecosystem.png?resize=449%2C304&amp;ssl=1" class="aligncenter wp-image-844 size-full" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/hadoop-ecosystem.png?resize=640%2C360&#038;ssl=1" alt="" width="640" height="360" data-recalc-dims="1" /></a></p>
  1227. <p>최근 들어서는 분산 파일 시스템인 HDFS를 대체 하는 기술들과 분산처리 기술인 맵리듀스(MapReduce)를 대체 하는 기술들도 이 생태계에 포함되었습니다.</p>
  1228. <p>&nbsp;</p>
  1229. <p>특히 <a href="https://spark.apache.org/">아파치 스파크(Spark)</a>의 경우 맵리듀스(MapReduce)를 충분히 대체할 수 있는 기술입니다. 아파치 재단에 따르면 스파크는 하둡 맵리듀스보다 최대 100배 더 빠르다고 합니다. 왜냐하면 스파크는 하드 드라이브로 읽고 쓰는 대신에 인 메모리(In-Memory)로 동작하고, 맵리듀스는 클러스터로부터 데이터를 읽고 연산을 수행하며 클러스터에 다시 결과를 작성하여 시간이 소요되는 반면에 스파크는 이 과정을 한 곳에서 수행하기 때문입니다. 아파치 스파크의 공식 자료에 따르면 <a href="https://spark.apache.org/news/spark-wins-daytona-gray-sort-100tb-benchmark.html">2016년 100테라바이트 정렬에 512개의 노드로 98.8초 만에 완료</a>하였다고 합니다. 스파크의 이러한 특징으로 인해 반복된 연산이 많이 발생하는 머신러닝과 같은 분야에서 그 효과가 극대화 됩니다.</p>
  1230. <p>&nbsp;</p>
  1231. <h3><strong>새로운 기술을 도입하는 것은 우리에게 꼭 필요한가?</strong></h3>
  1232. <p>여러 자료들을 살펴보고 간단한 작업들을 관련 기술들을 가지고 활용해 보았습니다. 그러는 과정에서 하둡이 좋고 스파크가 좋은 것은 알겠는데 그렇다면 그 기술을 도입하는 것이 현재 상황에서 적절한가를 고민해보았습니다. 기술을 도입하게 되면 서버도 필요하고 셋팅과 운영, 관리에 대한 리소스 뿐만 아니라 기술을 학습하는 시간도 필연적으로 필요하기 때문입니다.</p>
  1233. <p>&nbsp;</p>
  1234. <p>이러한 의문에 대한 답을 찾기 위해 여러 번의 실험을 진행하며 기술 도입에 대한 feasibility 검증을 진행해 보았습니다.</p>
  1235. <p>&nbsp;</p>
  1236. <p>큰 데이터를 빠르고 안정적으로 처리하는 부분이 저희 상황에서는 중요했습니다. 그렇기 때문에 많은 기업에서 채택하였고, 그 안정성 면에서도 검증이 되었던 하둡 맵리듀스(Hadoop MapReduce)를 가장 먼저 살펴보았습니다. 맵리듀스 프로그램은 Java로 구현해햐 하는데 매우 많은 코드 작성이 필요하고 어렵기 때문에 개발 생산성이 떨어지는 편입니다. 이를 보완하기 위해 스크립트 언어로 쉽게 맵리듀스 프로그래밍을 할 수 있는 Pig와 많은 사람들에게 익숙한 SQL로 프로그래밍 할 수 있는 Hive가 등장하였습니다. 실험에서는 현재 데이터를 생성하는 것 중에 가장 느리고 오래 걸리는 부분을 맵리듀스와 Pig, Hive로 구현하여 테스트하고 그 결과를 비교해 보았습니다.</p>
  1237. <p>&nbsp;</p>
  1238. <p><strong>기존 오래 걸렸던 지표를 맵리듀스(MapReduce), Pig, Hive로 실험한 결과 요약</strong></p>
  1239. <ul>
  1240. <li>기존 계산 방식의 10%의 소요시간으로 동일 작업을 완료</li>
  1241. <li>개발 생산성 면에서는 맵리듀스에 비해 Pig, Hive가 매우 높음 (코드 작성량 맵리듀스 대비 5%)</li>
  1242. <li>속도 면에서는 대량의 자료를 처리시 Pig, Hive에 비해 맵리듀스가 약 20% 정도 빠름</li>
  1243. <li>맵리듀스는 컴파일과 배포과정이 추가적으로 필요</li>
  1244. <li>Pig, Hive의 경우 수행 시간 뿐만 아니라 리소스 점유율(CPU, 메모리)이 높음</li>
  1245. <li>맵리듀스, Pig, Hive로 분산 처리 배치를 개발 할 경우 최적화 및 운영에 많은 시간이 소요될 것으로 예상</li>
  1246. </ul>
  1247. <p>이 실험을 통해 기술에 대한 충분한 학습시간 없이 테스트를 진행 했음에도 불구하고 그 결과는 꽤 만족스러웠습니다.</p>
  1248. <p>이 외에도 여러 번의 테스트와 데이터 요청에 대한 작업을 기존 방법이 아닌 맵리듀스, Pig, Hive, 스파크 등으로 테스트 해보면서 최종적으로는 빅데이터 분석을 위해 인프라를 구축하는 것이 좋겠다는 결론을 내렸습니다.</p>
  1249. <p>&nbsp;</p>
  1250. <h3><strong>어떤 기술들을 사용했을 때 문제를 해결할 수 있는가?</strong></h3>
  1251. <p>빅데이터 분석 인프라 구축을 결정하고 적합한 기술들을 선정하는 작업을 진행하였습니다. 기술들을 종류별로 나누고 요구사항과 부합하는지와 기술들 간의 비교를 통해 최종 기술들을 선정하였습니다.</p>
  1252. <p><strong> </strong></p>
  1253. <p><strong>데이터 처리는 스파크(Spark)!</strong></p>
  1254. <p>인프라 구성의 핵심은 스파크(Spark)였습니다. 기술들을 선정하는 과정에서 다른 기술들의 선택은 스파크를 지원하거나 보완하기 위해 선정했다고 할 수 있을 정도로 가장 중요한 부분이였습니다.</p>
  1255. <p>&nbsp;</p>
  1256. <p>데이터 처리 기술들을 검토하는 과정에서 6개월 정도의 API 로그(약 8억건, 700Gb)를 전수 살펴봐야 알 수 있는 데이터 요청 건이 있었습니다. 앱의 버그로 인해 API에 얼마나 많은 중복 요청이 발생하는지 파악하려는 이슈였습니다. 200ms의 시간내로 앱에서 API 서버로 같은 내용이 호출된 경우를 중복이라 가정하면 이른 기존 방법으로 분석하는 것은 쉽지 않은 작업입니다. 하지만 이를 스파크로 로직을 구현하고 AWS EC2의 c4.8xLarge 스펙의 인스턴스 1대에 셋팅하여 작업을 수행했을 때 4시간이라는 짧은 시간 동안 전체 데이터 분석을 완료할 수 있었습니다.</p>
  1257. <p>&nbsp;</p>
  1258. <p>스파크는 쉽게 사용할 수 있습니다. 구현 자체는 Scala로 되어 있지만 Java, Scala, Python, R로 프로그래밍 할 수 있도록 API를 제공합니다. 파이썬으로 하둡 HDFS에 저장된 파일을 읽어서 단어별 발생한 횟수를  계산하는 프로그램을 아래와 같은 형식으로 구현할 수 있습니다.</p>
  1259. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a3.png?ssl=1"><img data-attachment-id="878" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/a3/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a3.png?fit=358%2C100&amp;ssl=1" data-orig-size="358,100" 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="a3" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a3.png?resize=290%2C100&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a3.png?resize=358%2C100&amp;ssl=1" class="alignnone size-full wp-image-878" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a3.png?resize=358%2C100&#038;ssl=1" alt="" width="358" height="100" data-recalc-dims="1" /></a></p>
  1260. <p>&nbsp;</p>
  1261. <p>스파크는 많은 기능(Library)을 제공합니다. 가공하던 데이터를 임의의 테이블을 생성하고 쿼리로 조회 할 수 있고(Spark SQL), 실시간 데이터 처리도 쉽게 할 수 있습니다(Spark Streaming). 뿐만 아니라 머신러닝(MLlib), 그래프 분석(GraphX)도 쉽게 할 수 있도록 라이브러리를 제공할 수 있습니다. 데이터 준비, 기술적 분석(Descriptive analysis), 검색, 예측 분석, 기타 머신 학습과 그래프 프로세싱 등과 같은 고급분석에서도 별도의 기술이나 툴이 필요없이 스파크 만으로 가능합니다.</p>
  1262. <p>&nbsp;</p>
  1263. <p><strong>DB </strong><strong>데이터나 서버 로그를 가져오기 위한 Sqoop! Logstash!</strong></p>
  1264. <p>분산되어 있는 데이터를 가져와서 가장 먼저 S3에 저장하고 있습니다. HDFS에 저장하는 것도 검토하였지만 속도차이가 생각보다 크지 않았고 비용, 안정성, 생산성, 관리 이슈 등 많은 부분에서 S3가 더 만족스러웠기 때문입니다.</p>
  1265. <p>&nbsp;</p>
  1266. <p>DB에 있는 데이터는 데이터의 양이 많지 않으면 스파크에서 바로 가져와서 사용하고 있으며 데이터 양이 많을 경우 Sqoop을 이용해서 가져오고 있습니다. Sqoop은 HDFS, RDBMS, DW, NoSQL등 다양한 저장소에 대용량 데이터를 신속하게 전송할 수 있는 방법을 제공하고 있습니다. 이러한 다양한 저장소의 데이터를 Sqoop을 이용하면 간단히 매우 빠르게 가져올 수 있었습니다.</p>
  1267. <p>&nbsp;</p>
  1268. <p>서버 로그의 경우는 Flume, Fluentd, Logstash 등을 이용해서 가져올 수 있는데 기존 부터 <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/">ELK 스택을 이용해서 로그를 분석</a>하고 있었기 때문에 Logstash를 기존과 동일하게 사용하고 있으며 Elastic Search로 보낼 때 S3에도 함께 보내도록 설정하여 사용하고 있습니다.</p>
  1269. <p>&nbsp;</p>
  1270. <p><strong>로그 파일도 DB 테이블처럼, Presto! </strong></p>
  1271. <p>스파크를 이용하여 충분히 만족스럽게 데이터를 처리할 수 있었지만 개발에 대한 지식이 없는 다른 팀에게 데이터를 스파크를 이용해서 보게 하는 것은 매우 비효율적입니다. 스파크의 경우 대규모 데이터베이스에 상호적이고(Interactive), 즉각적인 쿼리를 실행 하는데는 적합하지 않습니다. 이러한 스파크의 단점을 보완하기 위해 Presto를 이용하였습니다.</p>
  1272. <p>Presto는 데이터를 SQL로 분석하는 Interactive Analysis에 최적화된 오픈 소스 분산 SQL 쿼리 엔진입니다. 페이스북에서 데이터 300PB 이상의 데이터 분석을 위해 개발하여 공개하였고, 현재 아파치 재단의 Top-Level 프로젝트로 등록되어 있습니다. 넷플릭스, Airbnb 등 많은 회사에서 사용하여 그 성능이 입증되었습니다.</p>
  1273. <p>스파크와 마찬가지로 메모리 상에서 데이터를 처리하여 매우 빠르고 효율적입니다. Presto를 사용함으로 인해 S3에 저장된 로그 등의 파일로 이루어진 데이터를 DB 테이블과 쉽게 조인하여 빠르게 분석할 수 있었고 모든 데이터에 대한 접근을 Presto를 통해 접근하게 함으로써 데이터에 대한 권한 관리도 효율적으로 할 수 있었습니다.</p>
  1274. <p>&nbsp;</p>
  1275. <p><strong>어떤 데이터든 SQL로 조회하고 간단히 시각화 할 수 있는 Superset!</strong></p>
  1276. <p>사실 Presto 자체는 데이터를 인터렉티브하게 조회 할 수 있는 엔진이기 때문에 다른 팀에서 사용하기에는 어려움이 있습니다. 단지 커맨드라인 툴만 제공하기 있기 때문에 SQL 명령어에 매우 익숙해야만 잘 사용할 수가 있습니다.</p>
  1277. <p>하지만 Superset을 이용하면 그런 불편함을 덜 수 있습니다. Superset은 데이터 분석을 쉽게 할 수 있도록 도와주는 Business Intelligence 웹 어플리케이션 입니다. Airbnb에서 개발하여 오픈소스로 공개한 프로젝트이며 현재는 Apache Incubating Project로 등록되어 있습니다.</p>
  1278. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/b.gif?ssl=1"><img data-attachment-id="846" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/b/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/b.gif?fit=1150%2C658&amp;ssl=1" data-orig-size="1150,658" 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="b" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/b.gif?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/b.gif?resize=449%2C304&amp;ssl=1" class="wp-image-846 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/b.gif?resize=791%2C453&#038;ssl=1" alt="" width="791" height="453" data-recalc-dims="1" /></a></p>
  1279. <p>백엔드를 Presto를 두어 사용할 수 있기 때문에 누구나 쉽게 관계형 데이터베이스에 저장된 데이터, 파일로 이루어진 정형화된 데이터들을 쉽게 분석해 볼 수 있습니다. 또한 간단한 대쉬보드로도 활용할 있어 별도의 대쉬보드 솔루션을 사용하지 않는다면 만족스럽게 활용해 볼 수 있습니다.</p>
  1280. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?ssl=1"><img data-attachment-id="847" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/c/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?fit=770%2C416&amp;ssl=1" data-orig-size="770,416" 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="c" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?resize=449%2C304&amp;ssl=1" class="wp-image-847 aligncenter" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?resize=798%2C431&#038;ssl=1" alt="" width="798" height="431" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?w=770&amp;ssl=1 770w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/c.gif?resize=768%2C415&amp;ssl=1 768w" sizes="(max-width: 798px) 100vw, 798px" data-recalc-dims="1" /></a></p>
  1281. <p>&nbsp;</p>
  1282. <p><strong>데이터를 자유 자재로 다룰 수 있게 도와주는 Zeppelin!</strong></p>
  1283. <p>데이터를 가공하는 작업의 경우 각 단계별 많은 데이터 검증이 필요합니다. 그렇기 때문에 프로그램을 짜고 디버깅해서 보는 것보다 코드 몇 줄을 짜고 바로 데이터를 확인해 볼 수 있는 인터렉티브한 방식이 효율적일 때가 많습니다. 제플린은 이를 불편한 커맨드라인이 아닌 웹에서 쉽고 효율적으로 해줄 수 있는 어플리케이션입니다. 제플린은 한국의 NF랩스에서 2013년 개발하였고 2014년 12월 아파치 인큐베이터 프로그램에 편입되었다가 그 후 1년반만에 Top-Level 프로젝트까지 되었습니다.</p>
  1284. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?ssl=1"><img data-attachment-id="848" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/z/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?fit=885%2C503&amp;ssl=1" data-orig-size="885,503" 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="z" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?resize=449%2C304&amp;ssl=1" class="wp-image-848 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?resize=811%2C461&#038;ssl=1" alt="" width="811" height="461" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?w=885&amp;ssl=1 885w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/z.png?resize=768%2C437&amp;ssl=1 768w" sizes="(max-width: 811px) 100vw, 811px" data-recalc-dims="1" /></a></p>
  1285. <p>스파크로 데이터를 분석할 때 매우 편리함은 물론 다양한 데이터베이스, 언어들의 인터프리터를 제공하고 있어 매우 활용도가 높습니다. 유사한 Jupyter Notebook을 함께 고려하였지만 타 팀과의 협업을 할 경우 제플린이 여러면에서 더 좋겠다고 판단하여 최종적으로는 제플린을 사용하고 있습니다.</p>
  1286. <p><strong> </strong></p>
  1287. <p><strong>데이터를 이 시간에 만들어줘! Airflow!</strong></p>
  1288. <p>데이터에 대한 요청은 스팟성 분석에 대한 요청도 많지만 지표와 같이 계속적으로 봐야하는 데이터들도 많습니다. 그 양이 적었을 경우 간단히 프로그램을 만들고 크론탭에서 스케줄로 등록할 수 있습니다. 하지만 그러한 배치 프로그램을 증가 하면 고려해야 할 부분이 매우 많습니다. 태스크들 간의 종속성도 관리해야 하고, 배치가 실패 했을 경우 이를 빨리 파악해서 조치하는 것도 필요합니다. 또한 현재 등록된 배치를 관리하고 모니터링 하는 것이 쉽지만은 않습니다. 이러한 작업을 효율적으로 할 수 있는 많은 어플리케이션(Airflow, Luigi, Pinball, Azkaban, Oozie 등)들이 존재합니다. 여러 방면에서 비교 검토를 통해 최종적으로 Airflow를 사용하게 되었습니다.</p>
  1289. <p><strong> <a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/airflow.gif?ssl=1"><img data-attachment-id="867" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/airflow/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/airflow.gif?fit=1454%2C960&amp;ssl=1" data-orig-size="1454,960" 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="airflow" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/airflow.gif?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/airflow.gif?resize=449%2C304&amp;ssl=1" class="aligncenter wp-image-867 size-full" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/airflow.gif?resize=1170%2C772&#038;ssl=1" alt="" width="1170" height="772" data-recalc-dims="1" /></a></strong></p>
  1290. <p>Airflow를 사용함으로써 전체 등록된 배치 프로그램들을 한눈에 살펴 보는 것 뿐만 아니라 각각의 프로그램의 단계별 현황까지 확인 후 쉽게 데이터 재생성과 같은 조치를 취할 수 있습니다. Slack과의 연동을 통해 실패할 경우 바로 파악해 볼 수도 있습니다.</p>
  1291. <p>&nbsp;</p>
  1292. <h3><strong>최종적인 모습은?</strong></h3>
  1293. <p>빅데이터 플랫폼을 활용한 데이터 인프라의 데이터 처리 단계별 사용하는 기술들의 흐름을 대략적으로 표현한 Conceptual Architecture는 아래와 같습니다.</p>
  1294. <p>크게는 데이터 다양한 데이터 저장소(Storage)에서 스케줄 등의 이벤트(Scheduling)를 통해 데이터를 가공(Processing)하여 저장(Warehouse) 하고,  저장된 데이터에서 최종적으로 사용자가 원하는 데이터를 쉽고 효율적으로 탐색 할 수 있게(Exploration) 하는 영역으로 나눌 수 있다. 경우에 따라서는 저장된 데이터를 효율적으로 볼 수 있도록 데이터의 구조 등을 저장(Meta Store)하여 활용될 수 있습니다.</p>
  1295. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?ssl=1"><img data-attachment-id="876" data-permalink="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/a1-2/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?fit=1017%2C484&amp;ssl=1" data-orig-size="1017,484" 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="a1" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?resize=449%2C304&amp;ssl=1" class="size-full wp-image-876 aligncenter" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?resize=1017%2C484&#038;ssl=1" alt="" width="1017" height="484" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?w=1017&amp;ssl=1 1017w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/08/a1-1.png?resize=768%2C365&amp;ssl=1 768w" sizes="(max-width: 1017px) 100vw, 1017px" data-recalc-dims="1" /></a></p>
  1296. <p>AWS의 EC2를 이용하여 인프라를 구성하였으며, Master Instance(m4.xlarge * 1개)와 Slave Instance Group(m4.xlarge * 2개) 로 이루어져 있습니다. Master Instance에는 분산 처리 솔류션들의 Master Process와 기타 솔류션들이 설치 되어 있으며, Slave Instance 그룹에는 분산 처리 솔류션들의 Slave Process들이 존재합니다.</p>
  1297. <p><strong> </strong></p>
  1298. <h3><strong>되돌아보면&#8230;</strong></h3>
  1299. <p>올해 초 검토를 시작으로 약 7개월 만에 현재와 같은 구성으로 운영되고 있습니다. 그동안 많은 분석 데이터와 지표들이 구성한 인프라를 통해 만들 졌으며, 많은 시행착오를 통해 현재는 어느 정도 안정적으로 운영되고 있습니다.</p>
  1300. <p>&nbsp;</p>
  1301. <p>그 중 가장 큰 시행착오를 이야기하면 초기 Amazon EMR을 통해 인프라를 구성하였다가 EC2에서 새로 구성한 것을 말씀 드릴 수 있을 것 같습니다. Amazon EMR은 Spark, Presto, Zeppelin 등 다양한 분산처리 하둡 프레임워크를 매우 쉽고 비용 효율적으로 구성할 수 있는 서비스 입니다. AWS에서 미사용 EC2 인스턴스를 입찰하여 사용할 수 있는 스팟 인스턴스를 이용하게 되면 최대 90% 이상 할인된 가격으로도 이용할 수 있습니다.</p>
  1302. <p>&nbsp;</p>
  1303. <p>하지만 스팟 인스턴스의 경우 입찰 비용을 초과하게 되면 서비스가 중단되는데, 인프라를 구성하는 과정에서 Superset, Airflow 등 중단되면 안되는 서비스가 추가되어 스팟 인스턴스를 이용할 수 없었고, 결정적으로는 EMR의 Master 서버가 예상치 못한 이슈로 중단되어 전체 구성을 복구했던 사건이 발생하여 검토 후 모두 EC2에서 새로 구성하는 작업을 하게 되었습니다. Master 서버가 중단된 이유는 서버의 디스크가 충분치 않아서 발생된 것으로 확인되었지만, Master 서버가 중단되면 EMR을 새로 구성해야 되는 것과 스팟 인스턴스를 사용할 수 없었던 이유로 인해 EC2로 전환하게 되었습니다. 현재 인프라로 처리하기 힘든 매우 큰 처리량이 필요한 스팟성 작업의 경우 EMR은 가장 먼저 검토할 것 같습니다.</p>
  1304. <p>&nbsp;</p>
  1305. <p>최근 많은 빅데이터 인프라 구성에서 고려하는 실시간 처리나 더 빠르고 효율적인 스토리지, 데이터 분석 서비스 등이 빠져있다고 생각할 수 있습니다. 현재의 인프라가 물론 최적은 아닙니다. 언제든지 다시 검토되어 사용하는 솔류션들이 추가될 수 있습니다. 하지만 인프라를 구성하면서 우리의 상황에서 가장 필요로 하는 구성을 계속적으로 고민하였고 그 흔적을 최대한 이 글에 남기려고 하였습니다. 비슷한 고민을 하거나 이러한 분야에 관심을 가진 사람들에게 약간 이라도 도움이 되었길 바라며 이 글을 마칩니다.</p>
  1306. <p>&nbsp;</p>
  1307. <h3><strong>References</strong></h3>
  1308. <ul>
  1309. <li><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/">안정적인 서비스 운영을 위한 서버 모니터링</a></li>
  1310. <li><a href="https://mydataexperiments.com/2017/04/11/hadoop-ecosystem-a-quick-glance/">Hadoop Ecosystem – A Quick Glance</a></li>
  1311. <li><a href="https://medium.com/airbnb-engineering/data-infrastructure-at-airbnb-8adfb34f169c">Data Infrastructure at Airbnb</a></li>
  1312. <li><a href="https://www.slideshare.net/JenAman/netflix-productionizing-spark-on-yarn-for-etl-at-petabyte-scale">Netflix &#8211; Productionizing Spark On Yarn For ETL At Petabyte Scale</a></li>
  1313. <li><a href="http://spark.apache.org/">Apache Spark</a></li>
  1314. <li><a href="http://hadoop.apache.org/">Apache Hadoop</a></li>
  1315. <li><a href="http://sqoop.apache.org/">Apache Sqoop</a></li>
  1316. <li><a href="https://superset.incubator.apache.org/">Apache Superset</a></li>
  1317. <li><a href="https://airflow.incubator.apache.org/">Apache Airflow</a></li>
  1318. <li><a href="https://zeppelin.apache.org/">Apache Zeppelin</a></li>
  1319. <li><a href="https://prestodb.io/">Presto</a></li>
  1320. </ul>
  1321. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/">빅데이터 프레임워크를 활용한 데이터 인프라 구축</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1322. ]]></content:encoded>
  1323. <wfw:commentRss>https://blog.dramancompany.com/2017/08/%eb%b9%85%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%94%84%eb%a0%88%ec%9e%84%ec%9b%8c%ed%81%ac%eb%a5%bc-%ed%99%9c%ec%9a%a9%ed%95%9c-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9d%b8%ed%94%84%eb%9d%bc-%ea%b5%ac%ec%b6%95/feed/</wfw:commentRss>
  1324. <slash:comments>7</slash:comments>
  1325. <post-id xmlns="com-wordpress:feed-additions:1">826</post-id> </item>
  1326. <item>
  1327. <title>AWS Code Deploy를 통한 배포 자동화</title>
  1328. <link>https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/</link>
  1329. <comments>https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/#comments</comments>
  1330. <pubDate>Mon, 17 Apr 2017 03:54:10 +0000</pubDate>
  1331. <dc:creator><![CDATA[Tom Kim]]></dc:creator>
  1332. <category><![CDATA[기술 블로그]]></category>
  1333. <category><![CDATA[AWS]]></category>
  1334. <category><![CDATA[Code Deploy]]></category>
  1335. <category><![CDATA[배포]]></category>
  1336.  
  1337. <guid isPermaLink="false">http://blog.dramancompany.com/?p=770</guid>
  1338. <description><![CDATA[<p>서버 배포는 단순하고 반복작업이지만 절차가 적지 않아 실수를 할 가능성이 높습니다. 또 한번의 실수는 커다란 시스템 장애로 이루어질 수 있기 때문에 많은 분들에게 배포란 꽤나 부담스럽고 큰 업무로 느껴집니다. 특히 하루에 여러번의 배포를 진행해야 하는 날이면 시간도 시간이지만 스트레스가 크죠. 드라마앤컴퍼니에서 이전까지는 서버 배포를 진행하는 개발자가 몇 없고 그들도 그 업무에 매우 익숙했기 때문에 큰<a class="button" href="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/" title="Read More">Read more</a></p>
  1339. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/">AWS Code Deploy를 통한 배포 자동화</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1340. ]]></description>
  1341. <content:encoded><![CDATA[<p>서버 배포는 단순하고 반복작업이지만 절차가 적지 않아 실수를 할 가능성이 높습니다. 또 한번의 실수는 커다란 시스템 장애로 이루어질 수 있기 때문에 많은 분들에게 배포란 꽤나 부담스럽고 큰 업무로 느껴집니다. 특히 하루에 여러번의 배포를 진행해야 하는 날이면 시간도 시간이지만 스트레스가 크죠.</p>
  1342. <p>드라마앤컴퍼니에서 이전까지는 서버 배포를 진행하는 개발자가 몇 없고 그들도 그 업무에 매우 익숙했기 때문에 큰 부담없이 진행할 수 있었지만, 배포를 진행해야 하는 개발자와 프로젝트의 수가 늘어남에 따라 배포로 인한 회사 전체의 업무 손실이 커졌습니다. 그래서 결국 계속 미뤄지던 배포 자동화의 첫 단계를 Code Deploy로 시작하기로 했습니다.</p>
  1343. <p>이번 글에서는 우선 Code Deploy가 생소한 분들을 위하여 개념을 쉽고 확실하게 설명드리고, 그 다음 최대한 삽질을 안하고 실제 적용을 하실 수 있도록 설명드리려고 합니다. 그리고 나서 저희는 어떻게 응용하여 사용하고 있는지, In-place와 새로 추가된 Blue/Green 배포 방식 등 이번에 알게 된 것들에 대하여 공유드리겠습니다.</p>
  1344. <p>&nbsp;</p>
  1345. <h1><strong>1. 개념</strong></h1>
  1346. <p>Code Deploy를 정말 간단히 설명하면 다음과 같습니다.</p>
  1347. <blockquote><p>서버에 코드를 자동으로 배포해주는 서비스</p></blockquote>
  1348. <p><a href="https://aws.amazon.com/ko/codedeploy/">https://aws.amazon.com/ko/codedeploy/</a></p>
  1349. <p>여기에 가보시면 친절한 설명 글과 멋져보이는 동영상 소개가 있습니다. 하지만 Code Deploy와 같은 개념이 생소하신 분들에게는 모호하게만 느껴질 수 있기 때문에 이 글에서는 천천히 설명드리려고 합니다.</p>
  1350. <p>&nbsp;</p>
  1351. <p>Code Deploy를 이용할 경우 배포는 다음과 같이 이루어집니다.</p>
  1352. <ol>
  1353. <li>배포할 코드 준비</li>
  1354. <li>Code Deploy에게 특정 리비전의 코드를 배포해달라고 요청</li>
  1355. <li>Code Deploy가 미리 지정해놓은 설정에 따라 새로운 서버(EC2 instance) 준비</li>
  1356. <li>새로운 서버에 설치되어있는 Code Deploy Agent 프로그램이 배포할 코드를 다운받음</li>
  1357. <li>코드를 프로젝트 경로로 복사한 뒤 미리 정의된 스크립트 실행 (필요한 모듈, 라이브러리 설치 등등의 작업 수행)</li>
  1358. <li>새로운 코드 준비가 완료되면 옛날 코드를 갖고 있는 서버들을 새로운 서버로 대체</li>
  1359. <li>배포 끝!</li>
  1360. </ol>
  1361. <p><img class="alignnone size-full" src="https://i1.wp.com/docs.aws.amazon.com/codedeploy/latest/userguide/images/sds_architecture.png?resize=784%2C420" width="784" height="420" data-recalc-dims="1" /></p>
  1362. <p>&lt;<a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html</a>&gt;</p>
  1363. <p>큰 흐름은 위와 같고 각 프로젝트의 필요에 따라 여러 옵션들을 지원합니다.</p>
  1364. <ul>
  1365. <li>코드를 Github에서 가져올지, S3에서 가져올지</li>
  1366. <li>기존에 실행되어있는 서버들에 배포를 진행(In-place deployment)할지 Blue/Green 방식으로 배포를 진행할지</li>
  1367. <li>실행되어있는 서버들이 여러개인 경우에 다양한 배포 전략 (한번에 하나씩 배포/절반씩 배포/전부 한꺼번에 배포)</li>
  1368. </ul>
  1369. <p>이 외에도 AWS답게 많은 옵션들을 지원합니다.</p>
  1370. <p>&nbsp;</p>
  1371. <p>그럼 저희가 Code Deploy를 도입하여 배포 과정이 어떻게 변경되는지 설명드리기 앞서 간략하게 저희의 배포 구조를 설명드리겠습니다. 드라마앤컴퍼니에서는 무중단 배포를 위하여 AWS Elastic Load Balancer(이하 ELB)와 AWS Auto Scaling Group(이하 ASG)을 이용한 Blue/Green 배포 방식을 사용하고 있습니다.</p>
  1372. <p>평소에는 클라이언트의 요청을 ELB에서 받고 1번 ASG로 요청을 보내줍니다. 배포를 하려고 하면 1번 ASG와 똑같은 크기와 설정을 갖는 2번 ASG를 만든 뒤에 ASG 내부에 새로운 코드를 갖고 있는 서버들을 추가합니다. 그리고 ELB에 새로 들어온는 요청들을 1번 ASG에서 2번 ASG로 보내게 하여 무중단 배포를 진행합니다.</p>
  1373. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?ssl=1"><img data-attachment-id="34" data-permalink="https://blog.dramancompany.com/2015/10/amazon-web-services-capistrano-%ea%b7%b8%eb%a6%ac%ea%b3%a0-%eb%a6%ac%eb%a9%a4%eb%b2%84/%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2015-09-25-16-17-37/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?fit=489%2C444&amp;ssl=1" data-orig-size="489,444" 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="스크린샷 2015-09-25 16.17.37" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?resize=300%2C272&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?resize=489%2C331&amp;ssl=1" class="alignnone size-full wp-image-34" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?resize=489%2C444&#038;ssl=1" alt="" width="489" height="444" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?w=489&amp;ssl=1 489w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png?resize=300%2C272&amp;ssl=1 300w" sizes="(max-width: 489px) 100vw, 489px" data-recalc-dims="1" /></a></p>
  1374. <p>기존에 저희가 사용하고 있던 운영 서버 배포 절차는 다음과 같습니다.</p>
  1375. <ol>
  1376. <li>Github에 코드 push</li>
  1377. <li>AMI용 instance 실행</li>
  1378. <li>코드 배포</li>
  1379. <li>실서버 테스트</li>
  1380. <li>AMI용 instance 종료</li>
  1381. <li>AMI 생성</li>
  1382. <li>Lauch Configuration 생성</li>
  1383. <li>Blue/Green 방식의 배포를 위하여 현재 활성화되어있지 않은 ASG (B 그룹)의 설정 변경(lauch configuration, scheduled action 등)</li>
  1384. <li>B그룹에 instance들 추가</li>
  1385. <li>Instance가 모두 생성되어 준비되면 ELB를 B그룹에 연결</li>
  1386. <li>A, B 그룹 모두 동시에 request를 보내다가 문제가 없으면 A그룹의 ELB를 연결 해제</li>
  1387. <li>모니터링을 진행하다가 문제가 없을 경우 A그룹의 instance 제거</li>
  1388. <li>A 그룹의 설정 변경 (scheduled action 등)</li>
  1389. </ol>
  1390. <p>정말 세세하게 항목들을 나열해서 많긴 하지만&#8230; 실제로도 많습니다 <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f62d.png" alt="😭" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
  1391. <p>Code Deploy를 이용하여 배포를 진행하면 배포 단계는 다음과 같이 바뀌게 됩니다.</p>
  1392. <ol>
  1393. <li>Github에 코드 push</li>
  1394. <li>AWS Code Deploy Console에서 새로운 배포 클릭</li>
  1395. <li>Git의 commit ID 입력</li>
  1396. <li><span style="color: #999999;">(자동으로) Auto Scaling Group 내부에 instance들이 하나씩 업데이트 되는 것을 지켜봄</span></li>
  1397. </ol>
  1398. <p>매우 간단해졌죠?</p>
  1399. <p>&nbsp;</p>
  1400. <h1><strong>2. 실전</strong></h1>
  1401. <p><a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-codedeploy.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-codedeploy.html</a></p>
  1402. <p>모든 과정은 이미 AWS에서 친절하고 자세하게 설명하고 있습니다. 이 글에서는 해당 문서에 숟가락만 얹어서 핵심 요약과 삽질 방지 팁을 알려드리도록 하겠습니다. 참고로 이 글은 Amazon Linux AMI, In-place 배포 방식을 기준으로 작성되었습니다.</p>
  1403. <p>&nbsp;</p>
  1404. <h2><strong>2-1. Profile 등 기본 설정</strong></h2>
  1405. <h4>a. IAM User 생성</h4>
  1406. <div><a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-provision-user.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-provision-user.html</a></div>
  1407. <div>사람이 하는 일을 프로그램이 대체하는 것이니 action을 대신하여 처리할 IAM user를 생성합니다.</div>
  1408. <p>&nbsp;</p>
  1409. <h4>b. Service Role 생성</h4>
  1410. <div><a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-service-role.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-service-role.html</a></div>
  1411. <div>
  1412. <p>앞서 만든 user가 AWS의 모든 서비스에 접근가능하면 안되겠죠? user에게 부여할 role을 만들어서 접근 가능한 리소스들을 지정해둡니다.</p>
  1413. <p>&nbsp;</p>
  1414. </div>
  1415. <h4>c. IAM instance profile 생성</h4>
  1416. <div><a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html</a></div>
  1417. <div>추후 해당 user가 Github이나 S3에서 코드를 가져올 때 필요한 profile을 생성합니다.</div>
  1418. <p>&nbsp;</p>
  1419. <p>&nbsp;</p>
  1420. <h2><strong>2.2 Instance 준비</strong></h2>
  1421. <h4>a. AMI용 instance 생성</h4>
  1422. <p>앞으로 배포를 하게될 EC2 instance를 미리 만들어둬야 합니다. 새로운 instance를 생성할 때 IAM Role를 앞서 생성한 role로 지정해야 합니다. 그 다음은 이 instance에 Code Deploy를 연동하기 위한 환경을 구성해야 합니다.</p>
  1423. <p>&nbsp;</p>
  1424. <h4>b. Code Deploy Agent 준비</h4>
  1425. <div>
  1426. <div><a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-run-agent-install.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-run-agent-install.html</a></div>
  1427. <div>서버가 실행됐을 때 우리가 지정한 코드를 불러와서 서버에 설치해주는 역할을 하는 Code Deploy Agent를 설치해둬야 합니다. Code Deploy Agent는 다음과 같이 동작합니다.</div>
  1428. </div>
  1429. <div>
  1430. <ol>
  1431. <li>서비스로 실행되어 서버가 시작될 때 같이 시작됨</li>
  1432. <li>새로 배포할 코드가 있다면 사용자가 지정한 코드 리비전을 다운받아서 임시 폴더에 저장</li>
  1433. <li>사용자가 정의해놓은 절차를 따라 script를 실행</li>
  1434. </ol>
  1435. <p>Code Deploy Agent의 로그를 각 instance에서 보고 싶으시면 <pre class="crayon-plain-tag">/var/log/aws/codedeploy-agent</pre>에서 확인할 수 있습니다.</p>
  1436. <p>&nbsp;</p>
  1437. <h4>c. Cloud Watch로 로그를 보내도록 처리</h4>
  1438. <div><a href="https://aws.amazon.com/ko/blogs/devops/view-aws-codedeploy-logs-in-amazon-cloudwatch-console/">https://aws.amazon.com/ko/blogs/devops/view-aws-codedeploy-logs-in-amazon-cloudwatch-console/</a></div>
  1439. <div>각 instance 내부에서 Code Deploy Agent의 로그를 볼 수 있습니다. 하지만 나중에 여러대의 서버에 배포를 진행하는데 문제가 생겼을 경우 모든 instance에 각각 들어가서 볼 수는 없겠죠? Cloud Watch로 모든 로그를 보내도록 처리합니다.</div>
  1440. <p>&nbsp;</p>
  1441. <h4>d. AMI 생성</h4>
  1442. <p>준비가 완료된 instance를 이용하여 AMI 이미지를 생성합니다.</p>
  1443. <p>&nbsp;</p>
  1444. <h4>e. Launch Configuration 생성</h4>
  1445. <p>Auto Scaling Group에서 새로운 instance를 추가할 때 어떤 instance를 생성할지 정의해놓는 launch configuration을 앞에서 만든 AMI 등을 이용하여 생성합니다.</p>
  1446. <h5>Tip!</h5>
  1447. <ul>
  1448. <li>프로젝트 파일들이 존재해야 할 곳에는 배포될 파일과 같은 이름의 파일들은 모두 지워두셔야 합니다. dot-file(.으로 시작하는 파일들)까지도 잊지말고 지워주셔야 합니다!<br />
  1449. <a href="http://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/troubleshooting-ec2-instances.html#troubleshooting-same-files-different-app-name">http://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/troubleshooting-ec2-instances.html#troubleshooting-same-files-different-app-name</a></li>
  1450. <li>이 글을 쓰는 시점에서는 codedeploy-agent이 특정 버전 이하의 aws-sdk-core에서만 동작하도록 처리되어있어서 aws-sdk-core의 버전이 너무 높으면 다음과 같은 메시지와 함께 에러가 나는 경우가 있습니다. (<em>Plugin codedeploy could not be loaded: Unable to activate codedeploy-commands-1.0.0, because aws-sdk-core-2.8.4 conflicts with aws-sdk-core (~&gt; 2.6.39)</em>)<br />
  1451. 이럴 경우 aws-sdk-core의 버전을 맞춰서 설치, 사용하면 됩니다.</li>
  1452. </ul>
  1453. </div>
  1454. <p>&nbsp;</p>
  1455. <h2><strong>2.3 Project 준비</strong></h2>
  1456. <h4>a. AppSpec.yml</h4>
  1457. <div><a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file.html</a></div>
  1458. <div></div>
  1459. <div>Code Deploy Agent가 프로젝트 코드를 다운받은 뒤 서버에 제대로 설치할 수 있게 절차를 알려줘야 합니다.</div>
  1460. <div>해당 내용을 정의해두는 파일이 AppSpec.yml 파일입니다. 해당 파일은 크게 files, permissions, hooks 세 가지 section으로 나뉩니다.</div>
  1461. <h5><strong>files</strong></h5>
  1462. <div>Code Deploy Agent가 서버의 임시 폴더에 다운받은 코드 파일들을 서버의 어떤 위치로 이동할지 정의합니다. destination이 우리의 어플리케이션의 코드가 위치할 곳입니다.</div>
  1463. <h5><strong>permissions</strong></h5>
  1464. <p>우리의 코드가 서버에서 제 위치를 찾은 뒤 어떤 permission을 갖고 있어야할지 정의해주는 부분입니다.</p>
  1465. <h5><strong>hooks</strong></h5>
  1466. <div>
  1467. <div>코드만 제 위치에 둔다고 어플리케이션이 작동하지는 않겠죠? 필요한 라이브러리, 모듈 등을 업데이트 설치도하고 asset들도 precompile한다던지 다양한 일을 해야 합니다. 이런 작업들은 script들로 미리 정의해둔 뒤에 필요한 시점에 호출할 수 있게 정의합니다.</div>
  1468. </div>
  1469. <ul>
  1470. <li>hook 문서 <a href="http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html">http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html</a></li>
  1471. <li>예시 <a href="https://github.com/awslabs/aws-codedeploy-samples">https://github.com/awslabs/aws-codedeploy-samples</a></li>
  1472. </ul>
  1473. <h5>Tip!</h5>
  1474. <ul>
  1475. <li>version은 무조건 0.0으로 고정해야 합니다. 실제 사용되는 값은 아니고 CodeDeploy에서 나중에 사용하려는 값으로 무조건 0.0을 입력하라고 하네요. 그러지 않을 경우 배포에 실패합니다.</li>
  1476. </ul>
  1477. <p>&nbsp;</p>
  1478. <h4>b. Script</h4>
  1479. <div>앞서 나온 AppSpec의 hooks 부분에서 호출할 스크립트들을 정의해둬야 합니다.</div>
  1480. <div>기호에 따라 두면 되겠지만 저는 project root에 scripts 디렉토리를 생성하여 내부에 shell script들을 작성해두었습니다.</div>
  1481. <div>저는 다음과 같은 script들을 사용합니다.</div>
  1482. <div>
  1483. <ul>
  1484. <li>서비스 시작</li>
  1485. <li>서비스 중지</li>
  1486. <li>서비스 정상 설치 확인<br />
  1487. <pre class="crayon-plain-tag">result=$(curl -s http://localhost:80/hello/)
  1488.  
  1489. if [[ "$result" =~ "Success" ]]; then
  1490.    exit 0
  1491. else
  1492.    exit 1
  1493. fi</pre>
  1494. </li>
  1495. <li>Gem 설치</li>
  1496. <li>기타 등등</li>
  1497. </ul>
  1498. <p>&nbsp;</p>
  1499. </div>
  1500. <h5>Tip!</h5>
  1501. <ul>
  1502. <li>script 파일들은 실행 권한을 갖고 있는채로 Git에 업로드 되어야 합니다  <pre class="crayon-plain-tag">chmod +x file_name</pre></li>
  1503. <li>hook의 location은 프로젝트의 root 경로를 기준으로 상대 경로를 사용하면 됩니다.</li>
  1504. <li>해당 스크립트가 실행되는 경로는 프로젝트가 복사된 후의 경로가 아닌 Code Deploy Agent가 설치된 경로 입니다 <pre class="crayon-plain-tag">/opt/codedeploy-agent</pre>. 따라서 프로젝트의 내부에 있는 파일들을 접근하고 싶으시다면 cd를 이용하여 디렉토리를 이동하시거나 절대경로로 사용하셔야 합니다</li>
  1505. <li>script log 파일을 보면 script가 실행되면서 남긴 log를 볼 수 있습니다 <pre class="crayon-plain-tag">/opt/codedeploy-agent/deployment-root/{deployment-group-ID}/{deployment-ID}/logs/scripts.log</pre>.</li>
  1506. </ul>
  1507. <p>&nbsp;</p>
  1508. <h2><strong>2.4 Auto Scaling Group 설정</strong></h2>
  1509. <p>이제 배포할 Auto Scaling Group을 지정합니다. 기존에 사용하던 ASG를 사용하셔도 됩니다. 대신 launch configuration은 이번에 생성한걸로 지정해줘야겠죠? 만약 특정 EC2 instance에 바로 배포를 진행하는 거라면 따로 처리하지 않으셔도 됩니다.</p>
  1510. <p>&nbsp;</p>
  1511. <h2><strong>2.5 CodeDeploy 설정</strong></h2>
  1512. <p>CodeDeploy에서는 Application, Deployment group, Deployment 세 가지의 개념을 이해하셔야 합니다.</p>
  1513. <h3>a. Application</h3>
  1514. <p>가장 상위 개념으로 CodeDeploy를 이용하여 배포를 진행할 프로젝트를 나타냅니다.</p>
  1515. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?ssl=1"><img data-attachment-id="799" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-11-14-02/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?fit=1666%2C604&amp;ssl=1" data-orig-size="1666,604" 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="Screen Shot 2017-04-14 at 11.14.02" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-799" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?resize=1170%2C424&#038;ssl=1" alt="" width="1170" height="424" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?w=1666&amp;ssl=1 1666w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.14.02.png?resize=768%2C278&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  1516. <p>&nbsp;</p>
  1517. <h3>b. Deployment group</h3>
  1518. <p>같은 application 내에 어떤 종류의 배포인지를 나타냅니다.<br />
  1519. 예를 들면 test/production 등 환경일 수 있고 특정 Auto Scaling Group일 수 있습니다.</p>
  1520. <p><img data-attachment-id="797" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-11-15-31/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?fit=2440%2C556&amp;ssl=1" data-orig-size="2440,556" 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="Screen Shot 2017-04-14 at 11.15.31" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-797" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?resize=1170%2C267&#038;ssl=1" alt="" width="1170" height="267" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?w=2440&amp;ssl=1 2440w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?resize=768%2C175&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.15.31.png?w=2340&amp;ssl=1 2340w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></p>
  1521. <p>생성 시 deployment type를 정할 수 있으며 배포할 대상(EC2, ASG 등)을 정할수도 있습니다.</p>
  1522. <p><img data-attachment-id="798" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-11-16-50/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.16.50.png?fit=1668%2C2044&amp;ssl=1" data-orig-size="1668,2044" 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="Screen Shot 2017-04-14 at 11.16.50" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.16.50.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.16.50.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-798" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.16.50.png?resize=1170%2C1434&#038;ssl=1" alt="" width="1170" height="1434" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.16.50.png?w=1668&amp;ssl=1 1668w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.16.50.png?resize=768%2C941&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></p>
  1523. <p>&nbsp;</p>
  1524. <h3>c. Deployments</h3>
  1525. <p>실제 배포 건을 나타냅니다.</p>
  1526. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?ssl=1"><img data-attachment-id="800" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-11-42-27/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?fit=2176%2C912&amp;ssl=1" data-orig-size="2176,912" 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="Screen Shot 2017-04-14 at 11.42.27" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-800" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?resize=1170%2C490&#038;ssl=1" alt="" width="1170" height="490" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?w=2176&amp;ssl=1 2176w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-11.42.27.png?resize=768%2C322&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  1527. <p>&nbsp;</p>
  1528. <h2><strong>2.6 배포</strong></h2>
  1529. <p>이제 배포를 진행합니다.<br />
  1530. 어떤 application의 어떤 그룹에다가 어떤 commit을 배포를 진행할지 적습니다.</p>
  1531. <p><a href="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?ssl=1"><img data-attachment-id="801" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-12-03-26/" data-orig-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?fit=1652%2C1718&amp;ssl=1" data-orig-size="1652,1718" 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="Screen Shot 2017-04-14 at 12.03.26" data-image-description="" data-medium-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-801" src="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?resize=1170%2C1217&#038;ssl=1" alt="" width="1170" height="1217" srcset="https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?w=1652&amp;ssl=1 1652w, https://i2.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.26.png?resize=768%2C799&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  1532. <p>배포 이력에서 배포 진행 현황을 살펴볼 수 있고, 성공 여부도 볼 수 있습니다.</p>
  1533. <p><a href="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?ssl=1"><img data-attachment-id="802" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-12-03-51/" data-orig-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?fit=3720%2C828&amp;ssl=1" data-orig-size="3720,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="Screen Shot 2017-04-14 at 12.03.51" data-image-description="" data-medium-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-802" src="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?resize=1170%2C260&#038;ssl=1" alt="" width="1170" height="260" srcset="https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?w=3720&amp;ssl=1 3720w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?resize=768%2C171&amp;ssl=1 768w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?w=2340&amp;ssl=1 2340w, https://i0.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.03.51.png?w=3510&amp;ssl=1 3510w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  1534. <p>View Events를 통하여 각 hook 부분 당 얼만큼의 시간이 소요되었으며 현재 어떤 과정을 거치고 있는지 실시간으로 확인할 수 있습니다.</p>
  1535. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?ssl=1"><img data-attachment-id="803" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-04-14-at-12-04-41/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?fit=2186%2C1010&amp;ssl=1" data-orig-size="2186,1010" 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="Screen Shot 2017-04-14 at 12.04.41" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-803" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?resize=1170%2C541&#038;ssl=1" alt="" width="1170" height="541" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?w=2186&amp;ssl=1 2186w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-04-14-at-12.04.41.png?resize=768%2C355&amp;ssl=1 768w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  1536. <p>에러가 났을 경우에는 script 실행 중 어떤 로그를 발생하면서 에러가 났는지도 확인할 수 있습니다.</p>
  1537. <p><a href="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?ssl=1"><img data-attachment-id="783" data-permalink="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/screen-shot-2017-03-30-at-11-04-59/" data-orig-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?fit=3698%2C724&amp;ssl=1" data-orig-size="3698,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="Screen Shot 2017-03-30 at 11.04.59" data-image-description="" data-medium-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?resize=290%2C220&amp;ssl=1" data-large-file="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?resize=449%2C304&amp;ssl=1" class="alignnone size-full wp-image-783" src="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?resize=1170%2C229&#038;ssl=1" alt="" width="1170" height="229" srcset="https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?w=3698&amp;ssl=1 3698w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?resize=768%2C150&amp;ssl=1 768w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?w=2340&amp;ssl=1 2340w, https://i1.wp.com/blog.dramancompany.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-30-at-11.04.59.png?w=3510&amp;ssl=1 3510w" sizes="(max-width: 1170px) 100vw, 1170px" data-recalc-dims="1" /></a></p>
  1538. <p>&nbsp;</p>
  1539. <h5>Tip!</h5>
  1540. <ul>
  1541. <li>CodeDeploy가 Rerouting traffic 단계로 넘어가기 전에 instance가 정상적으로 준비되었는지 확인하는 기준은 ELB의 health-check 경로입니다. 실제 instance에서 해당 주소를 호출했을 때 응답이 200으로 잘 오는지 확인하세요.</li>
  1542. </ul>
  1543. <p>&nbsp;</p>
  1544. <h1><strong>3. 그리고</strong></h1>
  1545. <h2>3.1 In-place vs Blue/Green Deployments</h2>
  1546. <p>2017년 1월에 In-place 배포 방법 외에 Blue/Green의 배포 방식이 추가되었습니다. (<a href="https://aws.amazon.com/ko/about-aws/whats-new/2017/01/aws-codedeploy-introduces-blue-green-deployments/">https://aws.amazon.com/ko/about-aws/whats-new/2017/01/aws-codedeploy-introduces-blue-green-deployments/</a>)<br />
  1547. Blue/Green의 배포 방식을 진행할 경우 다음과 같은 이점들이 있습니다.</p>
  1548. <ul>
  1549. <li>서버에 코드를 배포한 뒤 실제 요청을 받기 전에 테스트용 ELB 연결하여 테스트를 진행해볼 수 있습니다.</li>
  1550. <li>만약 새로 배포된 코드에 문제가 있을 경우, 요청을 예전 그룹으로 돌리기만 하기 때문에 재배포를 진행하는 것 보다 훨씬 빠르게 장애에 대응할 수 있습니다.</li>
  1551. <li>하나의 ASG에 3개의 서버가 떠있다고 가정했을 때, in-place 방식을 사용하면 최소 1대의 서버가 배포를 진행하느라 빠지기 때문에 나머지 서버들이 같은 양의 요청을 처리해야 합니다. 이는 장애의 위험을 증가시킵니다. Blue/Green 방식을 사용하면 기존의 3개는 요청을 처리하고 있고 새로운 3개가 추가되어 배포를 진행하기 때문에 이런 위험이 없습니다.</li>
  1552. </ul>
  1553. <p>따라서 저희는 기존에 사용하기도 했던 Blue/Green 방식을 이용하여 배포를 하려고 했습니다. Blue/Green 배포 방식을 사용하면 하나의 Auto Scaling Group만 갖고 있어도 Code Deploy에서 자동으로 해당 ASG의 설정과 값들을 복사하여 배포를 진행합니다. 하지만 나온지 얼마 되지 않은 기능이라 그런지 다음과 같은 이유들 때문에 사용하기 힘들다고 판단하여 in-place 방식을 택했습니다.</p>
  1554. <ul>
  1555. <li>Auto Scaling Group의 description 탭에서 현재 이 Auto Scaling Group이 어떤 ELB에 물려있는지 확인해야 하는데, CodeDeploy로 생성된 그룹에서는 해당 ELB가 보이지 않습니다(마치 아무 ELB에도 연결되어있지 않는 것으로 보입니다). 실제로 요청은 올바르게 들어옵니다. ELB를 물렸다 빼는 일은 굉장히 자주 일어나는 일이기 때문에 이런 작동 방식은 문제를 일으킬 위험이 매우 높다고 판단되었습니다. (이는 AWS 문의 결과 정상이라고 합니다.)</li>
  1556. <li>하나의 ASG에 하나의 ELB밖에 연결할 수 없습니다. (이는 AWS에 문의 결과 인지하고 있으며, 개선을 고려하고 있다고 합니다.)</li>
  1557. <li>하나의 서버에 하나의 프로젝트밖에 배포할 수 없습니다. Blue/Green의 로직 상, 아무런 소스코드도 깔려있지 않은 AMI로 만든 깡통 인스턴스가 실행되고 거기에 프로젝트를 배포하는 것이기 때문에 하나의 서버에 여러 프로젝트를 배포할 수 없습니다. (이도 AWS에 문의 결과 인지하고 있으며, 개선을 고려하고 있다고 합니다.)</li>
  1558. <li>새로 생성된 ASG은 임의의 이름으로 생성되기 때문에, CloudWatch alarm을 새로 만들어야 하고 CloudWatch dashboard에 새로 추가해야 합니다(..). 따라서 배포를 할 때마다 Scaling Policy를 위한 알람을 다시 매번 만들어주고 CloudWatch dashboard에 계속 추가하고 예전 그룹을 제거해줘야 합니다(&#8230;).</li>
  1559. </ul>
  1560. <p>위 내용은 글이 작성된 시점 (2017년 4월)에 확인된 내용이니 미래에는 바뀔 수 있습니다.</p>
  1561. <p>&nbsp;</p>
  1562. <h2>3.2 In-place 방식으로 Blue/Green 배포 진행하기</h2>
  1563. <p>위의 이유 때문에 어쩔 수 없이 in-place 방식을 택했습니다만, 기존까지 사용했던 Blue/Green의 이점도 포기하기 힘들었습니다.<br />
  1564. 따라서 조금 더 수작업이 들어가더라도 배포 방식을 약간 더 변경했습니다.</p>
  1565. <ul>
  1566. <li>기존처럼 ASG를 2개 만들어 둡니다.</li>
  1567. <li>새로 배포할 그룹에 배포를 in-place로 배포합니다.</li>
  1568. <li>테스트용 ELB를 물려서 테스트를 진행한 뒤 문제가 없을 경우 새로 배포된 그룹에 ELB를 물리고, 이전 그룹에서는 ELB를 제거합니다.</li>
  1569. </ul>
  1570. <p>ELB를 직접 관리해야한다는 번거로움은 있지만, 가장 불편한 AMI, Launch configuration 생성 과정은 생략할 수 있고 Blue/Green의 이점을 가져올 수 있기 때문에 이 방법을 택하기로 했습니다.</p>
  1571. <p>&nbsp;</p>
  1572. <h2>3.3 또 할 수 있는 것</h2>
  1573. <ul>
  1574. <li>이걸로 배포 자동화의 첫 단추를 끼웠습니다. 앞으로 Code Pipeline, Code Build 등와 연동하여 완성된 Continuous Delivery를 맞춰나갈 계획입니다.</li>
  1575. <li>예를 들면 Github webhook을 통해서 특정 branch에 배포가 이루어지면 자동으로 배포를 진행할 수 있습니다. 또한 Travis CI와 같은 CI tool들을 이용하신다면 빌드, 테스트가 성공적일 경우에 자동으로 배포를 진행할 수 있습니다. 테스트 서버와 develop branch를 연결해두면 참 편리하겠죠?</li>
  1576. <li>배포 상태(진행, 성공, 실패 등)에 대하여 SNS를 통해 이메일, Slack 등으로 알림도 받아볼 수 있습니다.</li>
  1577. <li>이 글에서는 Amazon Linux, Ruby 언어를 기준으로 배포를 진행했지만 Windows 등 다른 OS를 지원하고 코드의 언어에 전혀 종속적이지 않습니다.</li>
  1578. </ul>
  1579. <p>The post <a rel="nofollow" href="https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/">AWS Code Deploy를 통한 배포 자동화</a> appeared first on <a rel="nofollow" href="https://blog.dramancompany.com">DRAMA&amp;COMPANY</a>.</p>
  1580. ]]></content:encoded>
  1581. <wfw:commentRss>https://blog.dramancompany.com/2017/04/aws-code-deploy%eb%a5%bc-%ed%86%b5%ed%95%9c-%eb%b0%b0%ed%8f%ac-%ec%9e%90%eb%8f%99%ed%99%94/feed/</wfw:commentRss>
  1582. <slash:comments>9</slash:comments>
  1583. <post-id xmlns="com-wordpress:feed-additions:1">770</post-id> </item>
  1584. </channel>
  1585. </rss>
  1586.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda