<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.7">Jekyll</generator><link href="https://qpzm.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://qpzm.github.io/" rel="alternate" type="text/html" /><updated>2020-07-26T07:09:05+00:00</updated><id>https://qpzm.github.io/feed.xml</id><title type="html">Hyunmin Lee</title><subtitle>Hyunmin Lee's Dev blog</subtitle><entry><title type="html">느려도 너무 느린 Docker for mac의 bind mount 속도 개선 이야기</title><link href="https://qpzm.github.io/2020/03/23/docker-sync.html" rel="alternate" type="text/html" title="느려도 너무 느린 Docker for mac의 bind mount 속도 개선 이야기" /><published>2020-03-23T10:30:00+00:00</published><updated>2020-03-23T10:30:00+00:00</updated><id>https://qpzm.github.io/2020/03/23/docker-sync</id><content type="html" xml:base="https://qpzm.github.io/2020/03/23/docker-sync.html">&lt;h1 id=&quot;docker-for-mac의-bind-mount-속도-개선-이야기&quot;&gt;Docker for mac의 bind mount 속도 개선 이야기&lt;/h1&gt;

&lt;h2 id=&quot;똑같이-도커-컨테이너에서-돌리는데&quot;&gt;똑같이 도커 컨테이너에서 돌리는데…&lt;/h2&gt;
&lt;p&gt;AWS Codebuild 리눅스 호스트에서는 5분만에 전체 테스트가 돌아가는데 제 맥북에서는 25분이 걸립니다. 아래는 AWS 코드 빌드 general1.small(3 GB RAM, 2 vCPU ) 에서의 실행 결과입니다.&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;5 minutes 17 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 6.32 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
1965 examples, 0 failures
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;원인&quot;&gt;원인&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.docker.com/blog/user-guided-caching-in-docker-for-mac/&quot;&gt;도커 컨테이너가 MacOS 호스트에 있는 파일을 읽고 쓸 때는 시스템 콜 변환 과정을 거칩니다. 시스템 콜이 즉각적이라는 가정 하에 작성된 소프트웨어들은 이 사실을 모르기 때문에 수 만건 반복 요청을 보내도 합니다.&lt;/a&gt; 그래서 Docker-for-mac의 bind mount엔 작업에 따라 &lt;a href=&quot;https://docs.docker.com/docker-for-mac/osxfs/#performance-issues-solutions-and-roadmap&quot;&gt;속도 저하 문제&lt;/a&gt;가 생길 수 있습니다.&lt;/p&gt;

&lt;h3 id=&quot;잠깐-bind-mount와-volume&quot;&gt;잠깐! bind mount와 volume&lt;/h3&gt;
&lt;p&gt;둘 다 도커 호스트 머신에 파일을 저장하는 방법입니다. &lt;a href=&quot;https://docs.docker.com/storage/&quot;&gt;Manage data in Docker&lt;/a&gt;에 따르면 다음과 같은 차이가 있습니다.&lt;/p&gt;
&lt;h4 id=&quot;volumes&quot;&gt;volumes&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;호스트 파일 시스템 중 도커에 의해 관리되는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/lib/docker/volumes/&lt;/code&gt; 에 저장됩니다.&lt;/li&gt;
  &lt;li&gt;도커 이외의 프로세스가 수정해서는 안 됩니다.&lt;/li&gt;
  &lt;li&gt;볼륨의 이름만 명시하면 된다. 따라서 호스트에서의 파일 위치가 정해져 있지 않을 때, 예를 들면 개발 환경에서 호스트에서 편집한 코드를 컨테이너에 공유할 때 많이 씁니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;bind-mounts&quot;&gt;bind mounts&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/storage/bind-mounts/&quot;&gt;Bind mount&lt;/a&gt;는 도커 프로세스와 텍스트 편집기와 같은 도커 이외의 프로세스가 모두 내부 파일을 수정할 수 있습니다. 따라서 개발 환경에서 코드를 동기화하는 용도로 널리 쓰입니다.&lt;/li&gt;
  &lt;li&gt;마운트할 host machine의 full path를 명시해야 합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;해결&quot;&gt;해결&lt;/h2&gt;
&lt;p&gt;정말 답답해서 눈물이 나와 nfs 등 여러 가지를 시도해보았고 &lt;a href=&quot;https://docker-sync.readthedocs.io/&quot;&gt;docker-sync&lt;/a&gt;에 정착했습니다. 개인 맥북(2.7 GHz dual-core Intel Core i5, 8GB RAM, Docker에 2cpu, 4GB RAM 할당) 에선 전체 테스트 실행에 10분이 걸립니다. 개발할 때는 테스트 파일을 하나씩만 돌리니 유사 TDD를 할 만했습니다.&lt;/p&gt;

&lt;h3 id=&quot;step1-bind-mount를-external로-선언&quot;&gt;Step1. Bind mount를 external로 선언&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.override.yml&lt;/code&gt;를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;에 추가하면 docker-sync를 사용하지 않는 개발자들과의 호환성도 유지할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# docker-compose.override.yml&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3.4'&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;&amp;amp;app&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;app-code/:/var/www/app&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;app-code&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step2-install-docker-sync&quot;&gt;Step2. Install docker-sync&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docker-sync.readthedocs.io/en/latest/getting-started/installation.html#installation&quot;&gt;docker-sync&lt;/a&gt; 를 다운로드합니다.&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker-sync
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-sync start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step3-docker-syncyml-설정-파일-작성&quot;&gt;Step3. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-sync.yml&lt;/code&gt; 설정 파일 작성&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;2&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;syncs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;app-code&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;./'&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;sync_strategy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;native_osx'&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;sync_excludes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.git'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*.log'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;public/uploads'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step4-기존-컨테이너-삭제-후-재생성&quot;&gt;Step4. 기존 컨테이너 삭제 후 재생성&lt;/h3&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker-compose down&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;docker-compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;문제-해결&quot;&gt;문제 해결&lt;/h3&gt;

&lt;h4 id=&quot;1-xxx-file-not-found-에러가-발생합니다&quot;&gt;1. “xxx file not found” 에러가 발생합니다.&lt;/h4&gt;
&lt;p&gt;기존 볼륨을 지운 뒤 다시 Step 4번을 진행해주세요.&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker volume &lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;app-code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-도커-데몬을-껐다-켰더니-동기화가-안-됩니다&quot;&gt;2. 도커 데몬을 껐다 켰더니 동기화가 안 됩니다.&lt;/h4&gt;
&lt;p&gt;docker-sync가 별도의 컨테이너를 띄워서 bind mount와 내부 volume을 동기화해주는 방식으로 동작합니다. Docker-for-mac을 재시작한 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-sync start&lt;/code&gt;를 하지 않으면 파일이 업데이트되지 않습니다. 업데이트 내역은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-sync logs&lt;/code&gt; 로 확인할 수 있습니다. 자세한 원리는 &lt;a href=&quot;https://docker-sync.readthedocs.io/en/latest/advanced/how-it-works.html&quot;&gt;docker-sync 공식 문서&lt;/a&gt;를 참고하세요.&lt;/p&gt;

&lt;h2 id=&quot;비교&quot;&gt;비교&lt;/h2&gt;
&lt;p&gt;레일즈 프로젝트에서 rspec을 실행한 결과입니다. 둘 다 &lt;a href=&quot;https://github.com/rails/spring&quot;&gt;Spring preloader&lt;/a&gt;를 사용했습니다.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Default volume
    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bin/rspec spec/api/v1/task_boards/index_spec.rb
Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;14.64 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 6.91 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;docker-sync
    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bin/rspec spec/api/v1/task_boards/index_spec.rb
Finished &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;6.38 seconds &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;files took 0.7989 seconds to load&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;q--a&quot;&gt;Q &amp;amp; A&lt;/h2&gt;
&lt;h3 id=&quot;cached-또는-delegated-설정은-어떨까요&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cached&lt;/code&gt; 또는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegated&lt;/code&gt; 설정은 어떨까요?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/docker-for-mac/osxfs-caching/#tuning-with-consistent-cached-and-delegated-configurations%23tuning-with-consistent-cached-and-delegated-configuration&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegated&lt;/code&gt;를 적용하면 container의 파일 변화를 host에 전달하는 데 시간차가 생깁니다. 반대로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cached&lt;/code&gt; 를 적용하면 host의 파일 변화가 container에 즉시 전달되지 않을 수 있습니다.&lt;/a&gt; 우리는 호스트의 코드 변경 사항이 바로 컨테이너에 반영되기를 원하는 것이므로 어느 경우에도 해당되지 않습니다.&lt;/p&gt;</content><author><name>이현민 lhm1442@gmail.com</name></author><category term="Docker" /><summary type="html">Docker for mac의 bind mount 속도 개선 이야기</summary></entry><entry><title type="html">[Book] Metaprogramming in Ruby 2</title><link href="https://qpzm.github.io/2019/09/09/metaprogramming-ruby.html" rel="alternate" type="text/html" title="[Book] Metaprogramming in Ruby 2" /><published>2019-09-09T03:00:00+00:00</published><updated>2019-09-09T03:00:00+00:00</updated><id>https://qpzm.github.io/2019/09/09/metaprogramming-ruby</id><content type="html" xml:base="https://qpzm.github.io/2019/09/09/metaprogramming-ruby.html">&lt;h1 id=&quot;book-metaprogramming-in-ruby-2&quot;&gt;[Book] Metaprogramming in Ruby 2&lt;/h1&gt;

&lt;h2 id=&quot;ch2-the-object-model&quot;&gt;Ch2. The Object Model&lt;/h2&gt;
&lt;h3 id=&quot;instance-variable은-할당할-때-생긴다&quot;&gt;instance variable은 할당할 때 생긴다&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;Instance variables just spring into existence when you assign them a value, so you can have objects of the same class that carry different instance variables.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;instance-methods&quot;&gt;instance methods&lt;/h3&gt;
&lt;p&gt;An object’s methods live in the object’s class.&lt;/p&gt;

&lt;h3 id=&quot;class-vs-module&quot;&gt;class vs module&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;a class is a module with three additional instance methods (new, allocate, and superclass)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;a-class-is-just-an-object&quot;&gt;A class is just an object&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/18223805/62420415-c9fe9880-b6cc-11e9-9d17-8f5fdea70df1.png&quot; alt=&quot;A class is just an object&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;What’s a class? It’s an object (an instance of Class), plus a list of instance methods and a link to a superclass.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;question&quot;&gt;Question&lt;/h3&gt;
&lt;p&gt;모든 클래스의 클래스가 Class면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Class&lt;/code&gt;라는 클래스는 재귀적으로 정의되나?&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;ruby-class에-대한-보충-설명&quot;&gt;Ruby class에 대한 보충 설명&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intialize&lt;/code&gt; is not a constructor!&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;When Name.&lt;strong&gt;new&lt;/strong&gt; is called to create a new object, the &lt;strong&gt;new&lt;/strong&gt; class method in &lt;strong&gt;Class&lt;/strong&gt; is run by default, which in turn invokes &lt;strong&gt;allocate&lt;/strong&gt; to allocate memory for the object, before finally calling the new object’s &lt;strong&gt;initialize&lt;/strong&gt; method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;what-happens-when-you-call-a-method&quot;&gt;What happens when you call a method?&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;When you call a method, Ruby does two things:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;It finds the method. This is a process called &lt;em&gt;method lookup&lt;/em&gt;.&lt;/li&gt;
    &lt;li&gt;It executes the method. To do that, Ruby needs something called self.&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;method-lookup&quot;&gt;Method lookup&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;receiver&lt;/li&gt;
  &lt;li&gt;ancestors chain
    &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;MySubclass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ancestors&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [MySubclass, MyClass, Object, Kernel, BasicObject]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;modules-and-lookup&quot;&gt;Modules and lookup&lt;/h4&gt;
&lt;p&gt;include는 ancestors chain에서 해당 클래스 위에, prepend는 밑에 붙임. 따라서 prepend는 현재 클래스보다 더 우선. 아래 코드의 ancestors chain을 그려보자.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;D1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;C1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prepend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;D2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;C2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;BasicObject&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/18223805/62420541-b94f2200-b6ce-11e9-8b77-c8a965825ae3.png&quot; alt=&quot;Method lookup chain&quot; class=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;multiple-inclusion&quot;&gt;Multiple inclusion&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;if that module is already in the chain, Ruby silently ignores the second inclusion.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;M2가 M1을 include하지만 이미 M3에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prepend M1&lt;/code&gt;을 선언했기 때문에 무시된다.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M2&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prepend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M1&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;M3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ancestors&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [M1, M3, M2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-kernel&quot;&gt;The Kernel&lt;/h3&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;private_instance_methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;grep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^pr/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [:printf, :print, :proc]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Every line of Ruby is always executed inside an object, so you can call the instance methods in Kernel from anywhere. This gives you the illusion that print is a language keyword, when it’s actually a method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;what-private-really-means&quot;&gt;What private really means&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;Private methods are governed by a single simple rule: you cannot call a private method with an explicit receiver.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;methods-in-example-code&quot;&gt;Methods in example code&lt;/h3&gt;
&lt;h4 id=&quot;w&quot;&gt;\w&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;밑줄 문자를 포함한 영숫자 문자에 대응됩니다. [A-Za-z0-9_] 와 동일합니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;enumerablegrep&quot;&gt;Enumerable#grep&lt;/h4&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^re/&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [:reverse_each, :reverse, ..., :replace, ...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;arrayreplace&quot;&gt;Array#replace&lt;/h4&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&quot;x&quot;, &quot;y&quot;, &quot;z&quot;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;                              &lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&quot;x&quot;, &quot;y&quot;, &quot;z&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;ch3-methods&quot;&gt;Ch3. Methods&lt;/h2&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;data_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;grep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^get_(.*)_info$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Computer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define_component&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;method_missing&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_given?&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lawyer&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method_missing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You called: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;', '&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;(You also passed it a block)&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String#capitalize&lt;/code&gt;  : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String#upcase&lt;/code&gt; 와 구별&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Returns a copy of &lt;em&gt;str&lt;/em&gt; with the first character converted to uppercase and the remainder to lowercase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ch4-blocks&quot;&gt;Ch4. Blocks&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kernel#block_given?&lt;/code&gt; 으로 메소드에 블록이 주어졌는 지 알 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;quiz-using을-풀-때-유용한-정보&quot;&gt;Quiz using을 풀 때 유용한 정보&lt;/h3&gt;
&lt;h4 id=&quot;kernel-module&quot;&gt;Kernel module&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;The Kernel module is included by class  &lt;a href=&quot;file:///Users/hm/Library/Application%20Support/Dash/Versioned%20DocSets/Ruby%202%20-%20DHDocsetDownloader/2-5-3/Ruby.docset/Contents/Resources/Documents/Object.html&quot;&gt;Object&lt;/a&gt; , so its methods are available in every Ruby object.
 &lt;a href=&quot;http://ruby-doc.org/core-2.5.3/Kernel.html&quot;&gt;Module: Kernel (Ruby 2.5.3)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;the-main-object&quot;&gt;The main object&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;When a new program starts, Ruby automatically creates the main object which is an instance of the Object class. main is the top-level context of any program. This is probably a nod to the C language (as the main() function is the entry point of any C program and that Matz loves C)&lt;/p&gt;
  &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
  &lt;p&gt;https://medium.com/rubycademy/ruby-object-model-part-1-4d06fa486bec&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;ruby-exception-handling&quot;&gt;Ruby exception handling&lt;/h4&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# something which might raise an exception&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomeExceptionClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_variable&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# code that deals with some exception&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomeOtherException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_other_variable&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# code that deals with some other exception&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# code that runs only if *no* exception was raised&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ensure that this code always runs, no matter what&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# does not change the final value of the block&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;closure&quot;&gt;Closure&lt;/h3&gt;
&lt;p&gt;When you create the block, you capture the local bindings, such as x.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Goodbye&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cruel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_method&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;Hello, cruel world&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;block 안에서 만든 변수는 블록이 끝나면 사라짐. 이 두 가지 특징으로 인해 블록은 클로져다. For the rest of us, this means a block captures the local bindings and carries them along with it.&lt;/p&gt;

&lt;h3 id=&quot;-operator-turns-a-proc-to-a-block&quot;&gt;&amp;amp; operator turns a proc to a block&lt;/h3&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;!&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Bill&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;scope&quot;&gt;Scope&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kernel#local_variables&lt;/code&gt; 로 지역 변수를 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;ruby는 scope gate를 지날 때 마다 새 스코프로 교체된다.&lt;/p&gt;

&lt;h4 id=&quot;scope-gates&quot;&gt;Scope Gates&lt;/h4&gt;
&lt;p&gt;There are exactly three places where a program leaves the previous scope behind and opens a new one:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Class definitions&lt;/li&gt;
  &lt;li&gt;Module definitions&lt;/li&gt;
  &lt;li&gt;Methods
클래스나 모듈 스코프에 있는 코드는 바로 실행되는데 메소드 스코프에 있는 코드는 호출이 될 때야 비로서 실행된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Top level main object의 instance variable을 전역변수처럼 사용하는 예. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@var&lt;/code&gt;은 main이 self인 스코프에서 접근 가능하다.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;vi&quot;&gt;@var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The top-level @var&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@var&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;passing-scope-gates&quot;&gt;Passing scope gates&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ruby coders refer to it simply as “flattening the scope,” meaning that the two scopes share variables as if the scopes were squeezed together.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;my_var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_var&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in the class definition&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:my_method&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_var&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in the method&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;sharing-the-scope-without-global-var&quot;&gt;Sharing the scope without global var&lt;/h4&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;define_methods&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:counter&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:inc&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;define_methods&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 0 inc(4) counter # =&amp;gt; 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;instance_eval&quot;&gt;instance_eval()&lt;/h3&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;MyClass:0x3340dc @v=1&amp;gt; @v # =&amp;gt; 1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;The block is evaluated with the receiver as self, so it can access the receiver’s private methods and instance variables, such as @v. Even if instance_eval changes self, the block that you pass to instance_eval can still see the bindings from the place where it’s defined, like any other block:&lt;/p&gt;
  &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;자세한 내용은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BasicObject#instace_eval&lt;/code&gt; 문서를 참조하자.&lt;/p&gt;

&lt;h3 id=&quot;instance_exec-은-parameter를-넘겨줄-수-있음&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_exec&lt;/code&gt; 은 parameter를 넘겨줄 수 있음.&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_eval&lt;/code&gt; 로 해결할 수 없는 경우&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;twisted_method&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;@x: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, @y: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;twisted_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;@x: 1, @y: &quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_eval&lt;/code&gt; 은 self를 바꾸기 때문에 block이라 하더라도 이전 scope의 instance variable에는 접근할 수 없다. 이 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_exec&lt;/code&gt;을 사용하면 parameter를 넘겨주는 방법으로 해결할 수 있다.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;twisted_method&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;@x: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, @y: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;twisted_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &quot;@x: 1, @y: 2&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;proc-vs-lambda의-두-가지-차이&quot;&gt;Proc vs Lambda의 두 가지 차이&lt;/h3&gt;
&lt;h4 id=&quot;arity&quot;&gt;arity&lt;/h4&gt;
&lt;p&gt;lambda는 arity가 안 맞으면 에러. proc은 인자가 모자르면 nil을 넣고 남으면 무시함.&lt;/p&gt;

&lt;h4 id=&quot;return&quot;&gt;return&lt;/h4&gt;
&lt;p&gt;lambda에서 return 하면 method return과 동일하게 그 값을 반환.
Proc은 call된 스코프에서 return.&lt;/p&gt;

&lt;h3 id=&quot;method-objects&quot;&gt;Method objects&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Methods&lt;/em&gt;: Bound to an object, they are evaluated in that object’s scope. They can also be unbound from their scope and rebound to another object or class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Method는 callable object다. 아래와 같이 메소드를 변수에 저장하고 call할 수 있다.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:my_method&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;method---proc-block---method&quot;&gt;Method -&amp;gt; Proc, Block -&amp;gt; Method&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;you can convert a Method to a Proc by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Method#to_proc&lt;/code&gt;, and you can convert a block to a method with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;define_method&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;unbound-methods&quot;&gt;Unbound Methods&lt;/h4&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MyModule&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;unbound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:my_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;unbound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; UnboundMethod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://ruby-doc.org/core-2.5.3/UnboundMethod.html#￼method-i-bind&quot;&gt;UnboundMethod#bind&lt;/a&gt; 의 예시를 보자.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Bind &lt;em&gt;umeth&lt;/em&gt; to &lt;em&gt;obj&lt;/em&gt;. If Klass was the class from which &lt;em&gt;umeth&lt;/em&gt; was obtained, obj.kind_of?(Klass) must be true.
```ruby
class A
  def test
    puts “In test, class = #{self.class}”
  end
end
class B &amp;lt; A
end
class C &amp;lt; B
end&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;um = B.instance_method(:test)
bm = um.bind(C.new)
bm.call # =&amp;gt; In test, class = C
bm = um.bind(B.new)
bm.call # =&amp;gt; In test, class = B
bm = um.bind(A.new)
bm.call # =&amp;gt; prog.rb:16:in `bind’: bind argument must be an instance of B (TypeError) from prog.rb:16&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

## Ch5. Class Definitions
### The truth About Class Methods
&amp;gt; `Klass.a_class_method` calls a method on an object (that also happens to be a class) referenced by a constant.

&amp;gt; if you compare the definition of a Single- ton Method and the definition of a class method, you’ll see that they’re the same:
```ruby
def obj.a_singleton_method;  end
def MyClass.another_class_method; end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;class-macros&quot;&gt;Class Macros&lt;/h3&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deprecate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;warn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Warning: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old_method&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;() is deprecated. Use &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_method&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;().&quot;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;deprecate&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:GetTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;singleton-classes&quot;&gt;Singleton Classes&lt;/h3&gt;
&lt;p&gt;Where does a singleton class belong?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;an object can have its own special, hidden class. That’s called the &lt;em&gt;singleton class&lt;/em&gt;of the object. (You can also hear it called the &lt;em&gt;metaclass&lt;/em&gt;or the &lt;em&gt;eigenclass&lt;/em&gt;. However, “singleton class” is the official name.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;singleton_class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;singleton_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; Class&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Easier way&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton_class&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; #&amp;lt;Class:#&amp;lt;String:0x331df0&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;singleton classes have only a single instance (that’s where their name comes from), and they can’t be inherited. More important, &lt;em&gt;a singleton class is where an object’s Singleton Methods live&lt;/em&gt;:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_methods&lt;/code&gt; 임에 주의!&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;my_singleton_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;singleton_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;grep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/my_/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [:my_singleton_method]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;method-lookup-revisited&quot;&gt;Method Lookup Revisited&lt;/h3&gt;
&lt;p&gt;아래 코드의 method lookup 과정을 다시 한 번 그려보자.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;a_class_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;a_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;a_singleton_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/18223805/62420737-58294d80-b6d2-11e9-859f-f799d9d4d13c.png&quot; alt=&quot;method_lookup&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The superclass of the singleton class of an object is the object’s class. The superclass of the singleton class of a class is the singleton class of the class’s superclass.
한국어로 정리하면 아래와 같다.&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;오브젝트의 싱글톤 클래스의 수퍼클래스는 오브젝트의 클래스&lt;/li&gt;
    &lt;li&gt;클래스의 싱글톤 클래스의 수퍼 클래스는 수퍼클래스의 싱글톤 클래스&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;When you call a method, Ruby goes “right” in the receiver’s real class and then “up” the ancestors chain.
오른쪽의 singleton class를 먼저 보고 그 다음 위의 수퍼 클래스로 올라간다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;irb에서 출력해보면 singleton class 앞에는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; 가 붙는다.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton_class&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;lt;Class:#&amp;lt;String:0x00007fc6e9130918&amp;gt;&amp;gt; &amp;lt; String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;instance_eval의-진짜-의미&quot;&gt;instance_eval의 진짜 의미&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;you learned that instance_eval changes self, and class_eval changes both self and the current class. However, instance_eval also changes the current class; it changes it to the &lt;em&gt;singleton class&lt;/em&gt;of the receiver.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;add-a-class-method-through-including-a-module&quot;&gt;Add a class method through including a module&lt;/h3&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;MyModule&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'hello'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyModule&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;objectextend-is-a-shortcut&quot;&gt;Object#extend is a shortcut!&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object#extend&lt;/code&gt; 는 싱글톤 클래스에 모듈을 include한다.&lt;/p&gt;

&lt;h2 id=&quot;ch6-code-that-writes-code&quot;&gt;Ch6. Code that writes code&lt;/h2&gt;
&lt;h3 id=&quot;kerneleval&quot;&gt;Kernel#eval&lt;/h3&gt;
&lt;p&gt;문자열로 주어진 코드를 실행시킨다.&lt;/p&gt;

&lt;h3 id=&quot;binding-objects&quot;&gt;Binding objects&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;A Binding is a whole scope packaged as an object. The idea is that you can create a Binding to capture the local scope and carry it around.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;책의 예시를 보자.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;my_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# binding을 얻음&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;@x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kernel#binding&lt;/code&gt; 문서의 예시를 보자.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;binding&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;param&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;#=&amp;gt; &quot;hello&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;irb&quot;&gt;irb&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;irb is just a simple program that parses the standard input or a file and passes each line to eval.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;objecttaint&quot;&gt;Object#taint&lt;/h4&gt;
&lt;blockquote&gt;
  &lt;p&gt;Objects that are marked as tainted will be restricted from various built-in methods. This is to prevent insecure data, such as command-line arguments or strings read from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kernel#gets&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;hooks&quot;&gt;Hooks&lt;/h3&gt;
&lt;p&gt;상속, include, prepend, extend될 때 특정 코드를 실행시킨다.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inherited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subclass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; was inherited by &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subclass&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# String was inherited by MyString&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>이현민 lhm1442@gmail.com</name></author><category term="Ruby" /><category term="Metaprogramming" /><summary type="html">[Book] Metaprogramming in Ruby 2</summary></entry><entry><title type="html">Ruby mysql2 gem 설치 시 libssl 오류 해결법</title><link href="https://qpzm.github.io/2019/07/24/ruby-mysql2.html" rel="alternate" type="text/html" title="Ruby mysql2 gem 설치 시 libssl 오류 해결법" /><published>2019-07-24T06:00:00+00:00</published><updated>2019-07-24T06:00:00+00:00</updated><id>https://qpzm.github.io/2019/07/24/ruby-mysql2</id><content type="html" xml:base="https://qpzm.github.io/2019/07/24/ruby-mysql2.html">&lt;h1 id=&quot;ruby-mysql2-gem-설치-시-libssl-오류-해결법&quot;&gt;Ruby mysql2 gem 설치 시 libssl 오류 해결법&lt;/h1&gt;

&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;
&lt;p&gt;mysql2 gem 설치 과정에서  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libssl&lt;/code&gt; library가 없다는 오류가 발생했다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;❯❯❯ gem install mysql2
Building native extensions.  This could take a while...
ERROR:  Error installing mysql2:
        ERROR: Failed to build gem native extension.
(생략)
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/30834421/error-when-trying-to-install-app-with-mysql2-gem&quot;&gt;[1]&lt;/a&gt; 을 참고해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; 을 다시 설치해보도록 한다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libssl&lt;/code&gt; 이 없는데 왜 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt;을 설치해야하는 지 이상했는데,  &lt;a href=&quot;https://en.wikibooks.org/wiki/OpenSSL&quot;&gt;[2]&lt;/a&gt;에 따르면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt;이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libssl&lt;/code&gt;을 포함한다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OpenSSL consists of two separate libraries: libcrypto and libssl. libcrypto is a general-purpose cryptography library which can be used alone. libssl is a TLS library which depends on libcrypto.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;❯❯❯ brew reinstall openssl &amp;amp;&amp;amp; brew link openssl --force
(중략)
==&amp;gt; Summary
🍺  /usr/local/Cellar/openssl/1.0.2q: 1,794 files, 12.1MB
Warning: Refusing to link macOS-provided software: openssl
If you need to have openssl first in your PATH run:
  echo 'export PATH=&quot;/usr/local/opt/openssl/bin:$PATH&quot;' &amp;gt;&amp;gt; ~/.zshrc

For compilers to find openssl you may need to set:
  export LDFLAGS=&quot;-L/usr/local/opt/openssl/lib&quot;
  export CPPFLAGS=&quot;-I/usr/local/opt/openssl/include&quot;

For pkg-config to find openssl you may need to set:
  export PKG_CONFIG_PATH=&quot;/usr/local/opt/openssl/lib/pkgconfig&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/30834421/error-when-trying-to-install-app-with-mysql2-gem&quot;&gt;[1]&lt;/a&gt;의 다른 답변과 &lt;a href=&quot;https://bundler.io/v1.13/man/bundle-config.1.html#BUILD-OPTIONS&quot;&gt;[3]&lt;/a&gt;을 참고해 bundler 에 openssl의 경로를 찾을 수 있도록 옵션을 추가하고 다시 설치한다.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ bundle config --local build.mysql2 &quot;--with-ldflags=-L/usr/local/opt/openssl/lib —with-cppflags=-I/usr/local/opt/openssl/include&quot;
$ bundle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/30834421/error-when-trying-to-install-app-with-mysql2-gem&quot;&gt;mysql - Error when trying to install app with mysql2 gem - Stack Overflow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikibooks.org/wiki/OpenSSL&quot;&gt;OpenSSL - Wikibooks, open books for an open world&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bundler.io/v1.13/man/bundle-config.1.html#BUILD-OPTIONS&quot;&gt;Bundler: bundle config&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><category term="Ruby" /><summary type="html">Ruby mysql2 gem 설치 시 libssl 오류 해결법</summary></entry><entry><title type="html">AWS Codepipeline에서 파일 실행 권한이 사라지는 문제</title><link href="https://qpzm.github.io/2019/03/20/aws-codebuild.html" rel="alternate" type="text/html" title="AWS Codepipeline에서 파일 실행 권한이 사라지는 문제" /><published>2019-03-20T03:00:00+00:00</published><updated>2019-03-20T03:00:00+00:00</updated><id>https://qpzm.github.io/2019/03/20/aws-codebuild</id><content type="html" xml:base="https://qpzm.github.io/2019/03/20/aws-codebuild.html">&lt;h1 id=&quot;aws-codepipeline에서-파일-실행-권한이-사라지는-문제&quot;&gt;AWS Codepipeline에서 파일 실행 권한이 사라지는 문제&lt;/h1&gt;

&lt;h2 id=&quot;문제-발생&quot;&gt;문제 발생&lt;/h2&gt;
&lt;p&gt;Dockerfile에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENTRYPOINT&lt;/code&gt; 스크립트를 실행하도록 변경했다. 이후 AWS Codebuild만 단독으로 실행하면 정상 작동했는데 Codepipeline으로 Codebuild를 실행하니  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permission denied&lt;/code&gt; 에러가 발생했다.
참고로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run [SERVICE] [COMMAND]&lt;/code&gt;  를 실행하면 항상 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENTRYPOINT&lt;/code&gt;로 지정된 스크립트가 실행된다.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Container] 2019/03/20 08:48:36 Running command echo Testing...
Testing...
 [Container] 2019/03/20 08:48:36 Running command docker-compose run -e RAILS_ENV=test \
-e RAILS_MASTER_KEY_TEST=$RAILS_MASTER_KEY_TEST \
app /bin/sh -c &quot;rspec&quot;
 Creating network &quot;src_default&quot; with the default driver
Creating src_db_1 ...
·[1A·[2K
Creating src_db_1 ... ·[32mdone·[0m
·[1BError response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused &quot;exec: \&quot;./docker/app/docker-entry.sh\&quot;: permission denied&quot;: unknown
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;원인&quot;&gt;원인&lt;/h2&gt;
&lt;p&gt;S3로 소스코드를 압축해서 보내는 Codepipeline에서는 permission bits가 사라지는 문제가 있다고 한다. https://forums.aws.amazon.com/thread.jspa?threadID=235452&lt;/p&gt;

&lt;h2 id=&quot;해결&quot;&gt;해결&lt;/h2&gt;
&lt;p&gt;Codebuild의  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buildspec.yml&lt;/code&gt; 에서 다시 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod +x ./docker/app/docker-entry.sh&lt;/code&gt;를 실행했다.&lt;/p&gt;</content><author><name></name></author><category term="Docker" /><category term="AWS" /><summary type="html">AWS Codepipeline에서 파일 실행 권한이 사라지는 문제</summary></entry><entry><title type="html">도커(Docker), AWS Codebuild, CodePipeline을 활용한 레일즈(Ruby on Rails) 개발과 배포</title><link href="https://qpzm.github.io/posts/intro_to_docker" rel="alternate" type="text/html" title="도커(Docker), AWS Codebuild, CodePipeline을 활용한 레일즈(Ruby on Rails) 개발과 배포" /><published>2019-03-13T03:00:00+00:00</published><updated>2019-03-13T03:00:00+00:00</updated><id>https://qpzm.github.io/posts/intro-to-docker</id><content type="html" xml:base="https://qpzm.github.io/posts/intro_to_docker">&lt;h1 id=&quot;docker-aws-codebuild-codepipeline을-활용한-ruby-on-rails-개발과-배포&quot;&gt;Docker, AWS Codebuild, CodePipeline을 활용한 Ruby on Rails 개발과 배포&lt;/h1&gt;

&lt;p&gt;도커에 대한 간략히 이해하고 레일즈 개발에 적용해 봅니다. 쓰다 보면 궁금해지므로 원리보다는 사용 방법에 집중합니다. 🙋 라벨이 붙은 내용은 넘어가도 좋습니다.&lt;/p&gt;

&lt;h2 id=&quot;1-굳이-왜&quot;&gt;1. 굳이 왜?&lt;/h2&gt;
&lt;h3 id=&quot;쉽고-빠른-환경-설정&quot;&gt;쉽고 빠른 환경 설정&lt;/h3&gt;
&lt;p&gt;새 프로젝트를 시작하면 세팅하다 하루가 다 가곤 한다. 이제 Docker 를 이용하면 두 줄로 끝난다.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker-compose build
docker-compose up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;불변-배포-immutable-deployment&quot;&gt;불변 배포 (Immutable deployment)&lt;/h3&gt;

&lt;p&gt;과거의 나는 서버에 도대체 무슨 짓을 벌였는가?  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rvm&lt;/code&gt;  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt; 등 온갖 패키지, 설정 파일의 향연에 좌절하곤 했다.&lt;/p&gt;

&lt;p&gt;쉽게 똑같은 서버를 구성할 수 있다면 서버 관리, 롤백, Scaling에 유리하다.&lt;/p&gt;

&lt;h2 id=&quot;2-도커-맛보기&quot;&gt;2. 도커 맛보기&lt;/h2&gt;

&lt;p&gt;도커는 어플리케이션을 개발, 배포, 실행하기 위한 오픈소스 플랫폼입니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://docs.docker.com/storage/storagedriver/images/sharing-layers.jpg&quot; alt=&quot;Containers sharing same image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;이미지&quot;&gt;이미지&lt;/h3&gt;

&lt;p&gt;뜯기 전 3분 카레. Mysql docker image라면 mysql을 실행시킬 수 있게 코드, 의존성 패키지, 환경변수 등 모든 것이 준비되어 있다. Dockerfile을 빌드해서 만들며 여러 개의 레이어로 이뤄진다.&lt;/p&gt;

&lt;h3 id=&quot;컨테이너&quot;&gt;컨테이너&lt;/h3&gt;

&lt;p&gt;전자레인지에 돌린 3분 카레. 이미지를 실행시키면 컨테이너가 된다. Mysql 이미지의 컨테이너는 실제로 Mysql을 사용가능하다. 도커 이미지에 새 Read/Write layer를 올려서 만들어지고 종료 시 해당 레이어는 지워진다.&lt;/p&gt;

&lt;h3 id=&quot;기본-명령어&quot;&gt;기본 명령어&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run docker/whalesay cowsay &lt;span class=&quot;s2&quot;&gt;&quot;난다 고래?&quot;&lt;/span&gt;
docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; docker/whalesay /bin/sh
docker ps &lt;span class=&quot;c&quot;&gt;# 실행중인 컨테이너 목록&lt;/span&gt;
docker ps &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 모든 컨테이너 목록&lt;/span&gt;
docker stop &amp;lt;container-id&amp;gt;
docker &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &amp;lt;container-id&amp;gt; &lt;span class=&quot;c&quot;&gt;# 컨테이너 삭제&lt;/span&gt;
docker image &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 이미지 목록&lt;/span&gt;
docker rmi &amp;lt;image-id&amp;gt; &lt;span class=&quot;c&quot;&gt;# 이미지 삭제&lt;/span&gt;
docker system prune &lt;span class=&quot;c&quot;&gt;# 안 쓰는 컨테이너, 이미지 모두 삭제&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;레일즈-도커-파일-예시&quot;&gt;레일즈 도커 파일 예시&lt;/h3&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ruby:2.5.3 # ubuntu with ruby 2.5.3&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;apt-get update &lt;span class=&quot;nt&quot;&gt;-qq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; build-essential libpq-dev nodejs imagemagick &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; RAILS_ROOT /var/www/app&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$RAILS_ROOT&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; $RAILS_ROOT&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; Gemfile* ./&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;bundler &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'1.16.4'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; bundler config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; frozen 1
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;bundle &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;VOLUME&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; $RAILS_ROOT&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;EXPOSE&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 3000&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; bundle exec rails db:migrate &amp;amp;&amp;amp; bundle exec puma -C config/puma.rb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;volume&quot;&gt;VOLUME&lt;/h4&gt;

&lt;p&gt;볼륨은 외부 저장 장치처럼 호스트의 저장공간을 쓰기 위해. DB 저장에 흔히 사용하는데 이유는 다음과 같다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;컨테이너를 지워도 볼륨에 저장한 데이터는 남아있다.&lt;/li&gt;
  &lt;li&gt;볼륨에 기록하면 이미지 크기가 늘어나지 않는다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;단 dockerfile에서 VOLUME 명령어는 mount point, 즉 빈 폴더만 만든다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run -v &amp;lt;host_path&amp;gt;:&amp;lt;container_path&amp;gt; &lt;/code&gt; 를 통해 실제로 마운트할 수 있다.&lt;/p&gt;

&lt;h4 id=&quot;expose&quot;&gt;EXPOSE&lt;/h4&gt;

&lt;p&gt;docker run 할 때 해당 포트를 사용하라는 표시.
실효는 없고 사용자에게 남기는 주석이다. (AWS 배포하는 플랫폼에 따라 이 표시를 활용하는 경우도 있다)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In Docker 1.10 and higher, only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RUN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COPY&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ADD&lt;/code&gt; instructions create layers. Other instructions create temporary intermediate images, and no longer directly increase the size of the build.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;https://docs.docker.com/v17.09/engine/userguide/eng-image/dockerfile_best-practices/#minimize-the-number-of-layers&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RUN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COPY&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ADD&lt;/code&gt; 세 명령어는 이미지 레이어를 만든다. 빌드할 때 아래 레이어가 변경된 경우, 그 위 레이어들을 전부 새로 빌드하므로 명령어 배치에 유의하자.&lt;/p&gt;

&lt;p&gt;🙋🏼‍♀️Dockerfile부터 직접 이미지를 빌드해 보자: &lt;a href=&quot;https://docs.docker.com/get-started/part2/&quot;&gt;공식 튜토리얼&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;정리&quot;&gt;정리&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;컨테이너는 추상화된 어플리케이션이다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;추상화-abstraction&quot;&gt;추상화 (Abstraction)&lt;/h4&gt;

&lt;p&gt;중요한 것만 남기는 것. 3분 카레도 카레다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;숫자: 1000원을 받으면 100원 짜리가 몇 개인지 신경쓰지 않는다.&lt;/li&gt;
  &lt;li&gt;OS의 하드웨어 추상화: 안드로이드 앱은 다양한 기기에서 실행된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;vm-vs-container&quot;&gt;VM vs Container&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;https://www.docker.com/sites/default/files/d8/2018-11/docker-containerized-and-vm-transparent-bg.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.docker.com/resources/what-container&quot;&gt;도커 공식문서&lt;/a&gt;에 따르면 컨테이너는 코드와 의존 패키지를 포함한 어플리케이션, 즉 OS 커널 위에서 실행되는 프로그램을 추상화한다. 반면, 가상머신은 컴퓨터 하드웨어를 추상화한다. 도커 컨테이너들은 OS 커널을 공유하기 때문에 더 적은 용량을 차지한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;잠깐!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;도커는 namespace(독립된 프로세스 공간), cgroup(리소스 제한) 등의 리눅스의 기능을 활용해서 만들어졌다. 따라서 Docker for mac은 리눅스를 돌리기 위한 가상머신을 추가로 설치한다.&lt;/p&gt;

&lt;h2 id=&quot;3-docker-compose&quot;&gt;3. docker-compose&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; 파일을 정의하고 해당 파일이 있는 폴더에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose 명령어 &lt;/code&gt; 를 입력하면 여러 컨테이너를 한 번에 관리하고 옵션을 생략할 수 있어 편리하다.&lt;/p&gt;

&lt;h3 id=&quot;️-기본-명령어&quot;&gt;⭐️ 기본 명령어&lt;/h3&gt;

&lt;h4 id=&quot;이미지-빌드-후-컨테이너-실행&quot;&gt;이미지 빌드 후 컨테이너 실행&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;한 번도 빌드한 적이 없어 아직 이미지가 없을 때&lt;/li&gt;
  &lt;li&gt;Gemfile을 수정했을 때&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker-compose build
docker-compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;
docker-compose logs &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;터미널-명령어-입력&quot;&gt;터미널 명령어 입력&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;app bash
root@35b0e137ef35:/var/www/app# e.g. bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;rails db:migrate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;컨테이너-종료&quot;&gt;컨테이너 종료&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker-compose down
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;🙋 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt;를 이용해 레일즈, postgresql을 실행해보자: https://docs.docker.com/compose/rails/&lt;/p&gt;

&lt;h3 id=&quot;-docker-composeyml-구성&quot;&gt;🙋 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; 구성&lt;/h3&gt;

&lt;p&gt;예시 레일즈 프로젝트의  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/docker-compose.yml&lt;/code&gt; 을 살펴보자.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3.2'&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# use compose format v3&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dockerfile&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./docker/app/Dockerfile&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;cache_from&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${AWS_ECR_REPO}/rails:1.0.3&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${AWS_ECR_REPO}/rails:1.0.3&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./:/var/www/app&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./config/database-docker.yml:/var/www/app/config/database.yml&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;expose&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3000&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;RAILS_ENV=development&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 시작 순서를 조정, 단 해당 container의 started 상태만 보장, 내부적 준비 여부는 모름.&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql:5.7&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./db/development:/var/lib/mysql&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;expose&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3306&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;xxx&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;xxx&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;web&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./docker/web/&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;cache_from&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${AWS_ECR_REPO}/nginx:1.0.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${AWS_ECR_REPO}/nginx:1.0.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;80:80&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;4000:3000&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# dev&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4-staging-서버로-배포&quot;&gt;4. Staging 서버로 배포&lt;/h2&gt;

&lt;h3 id=&quot;️-배포-과정&quot;&gt;⭐️ 배포 과정&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt; 브랜치에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt;과 ` Dockerrun.aws.json` 의 레일즈 이미지 태그를 새 릴리즈 버전과 동일하게 업데이트 후 커밋&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staging &lt;/code&gt; 브랜치로 pull request &amp;amp; squash and merge&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;AWS Codebuild 와 Codepipeline에 의해 ElasticBeanstalk에 자동 배포&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staging&lt;/code&gt; 브랜치에 대한 푸시 권한을 제한하면 무분별한 배포를 막을 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;codebuild&quot;&gt;Codebuild&lt;/h3&gt;

&lt;p&gt;도커 이미지를 빌드하고 이미지 저장소에 업로드&lt;/p&gt;

&lt;p&gt;로컬에 AWS CLI가 설치되어 있다면 아래의 순서로 이미지 저장소에 푸시할 수 있다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aws configure&lt;/code&gt; 명령어를 통해 해당 저장소에 업로드 권한이 있는 유저로 로그인&lt;/li&gt;
  &lt;li&gt;아래 build script의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; 다음에 나오는 명령어들을 순서대로 입력&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/buildspec.yml&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.2&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# build spec version&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;AWS_DEFAULT_REGION&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ap-northeast-2&quot;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;phases&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;pre_build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;echo Logging into Amazon ECR...&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;echo Pulling Docker Images for cache...&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;docker-compose pull --ignore-pull-failures -q&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;docker-compose build&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;post_build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;docker-compose push&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;artifacts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;./**/*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;codepipeline&quot;&gt;Codepipeline&lt;/h3&gt;

&lt;p&gt;Github 소스코드를 Codebuild에 전달하고 ElasticBeanstalk에 배포&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/18223805/54255510-bc206d80-459b-11e9-983f-78aa42b95697.png&quot; alt=&quot;image-20190313041603062&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;️-aws-elasticbeanstalk-세부-내용&quot;&gt;🙋🏼‍♀️ AWS ElasticBeanstalk 세부 내용&lt;/h3&gt;

&lt;p&gt;AWS ElasticBeanstalk Multicontainer docker 환경을 사용한다. 이는 내부적으로 컨테이너 관리 서비스인 Elastic Container Service를 이용하며 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; 과 유사한 아래의 설정파일이 필요하다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Dockerrun.aws.json&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AWSEBDockerrunVersion&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;containerDefinitions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;environment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;RAILS_ENV&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;production&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;essential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;memory&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;512&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;386640523397.dkr.ecr.ap-northeast-2.amazonaws.com/rails:1.0.3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mountPoints&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;containerPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/www/app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sourceVolume&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Performance_Plus_Rails&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;containerPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/www/app/config/database.yml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sourceVolume&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Performance_Plus_Rails_DB_Config&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;essential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;memory&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;512&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;386640523397.dkr.ecr.ap-northeast-2.amazonaws.com/nginx:1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mountPoints&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;containerPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/www/app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sourceVolume&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Performance_Plus_Rails&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;links&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;web&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;portMappings&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;containerPort&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;hostPort&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;volumes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Performance_Plus_Rails&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sourcePath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/app/current/&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;elasticbeanstalk가&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;기본으로&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;파일을&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;업로드하는&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;위치&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Performance_Plus_Rails_DB_Config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sourcePath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/app/current/config/database-docker.yml&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;links&quot;&gt;links&lt;/h4&gt;
&lt;p&gt;docker-compose는 자동으로 컨테이너 이름을 이용해 다른 컨테이너에 접속할 수 있게 도와준다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/docker/web/nginx.conf&lt;/code&gt; 의 일부&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;upstream&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rails_app&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# app is defined in Dockerrun.aws.json &quot;link&quot;: [&quot;app&quot;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;추후 &lt;a href=&quot;https://docs.docker.com/network/links/&quot;&gt;deprecated 예정&lt;/a&gt;이니 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;network&lt;/code&gt; 옵션으로 바꿀 계획. 자세한 옵션 설명은 &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html&quot;&gt;Task Definition Parameters - Amazon Elastic Container Service&lt;/a&gt; 을 참조하자.&lt;/p&gt;

&lt;h4 id=&quot;q-db-이미지는-어디로-갔나요&quot;&gt;Q. db 이미지는 어디로 갔나요?&lt;/h4&gt;
&lt;p&gt;DB는 rds로 운영하므로 필요없다!&lt;/p&gt;

&lt;h2 id=&quot;결론&quot;&gt;결론&lt;/h2&gt;

&lt;p&gt;⭐️ 만 익히고 쓰면서 찾아보자.&lt;/p&gt;

&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;2. 도커 맛보기&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;도커의 정의, 원리 https://docs.docker.com/engine/docker-overview/&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Dockerfile부터 도커 허브에 푸시까지 [Get Started, Part 2: Containers&lt;/td&gt;
      &lt;td&gt;Docker Documentation](https://docs.docker.com/get-started/part2/)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Dockerfile 작성 시 유의사항 https://docs.docker.com/v17.09/engine/userguide/eng-image/dockerfile_best-practices/&lt;/p&gt;

&lt;p&gt;Layer 관점에서 본 이미지와 컨테이너 https://docs.docker.com/storage/storagedriver/&lt;/p&gt;

&lt;p&gt;컨테이너는 어플리케이션의 추상화&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;[What is a Container?&lt;/td&gt;
          &lt;td&gt;Docker](https://www.docker.com/resources/what-container)&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.docker.com/2016/03/containers-are-not-vms/&quot;&gt;Containers are not VMs - Docker Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;namespace와 cgroup https://tech.ssut.me/what-even-is-a-container/&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. docker-compose&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/compose/compose-file/&quot;&gt;명령어 docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/compose/rails/&quot;&gt;docker-compose를 이용한 레일즈, postgresql 실행&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4, Staging 서버로 배포&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/create_deploy_docker_ecs.html&quot;&gt;AWS ElasticBeanstalk Multicontainer docker 환경 튜토리얼&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerrun.aws.json&lt;/code&gt; 의 설정 옵션 &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html&quot;&gt;Task Definition Parameters - Amazon Elastic Container Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;도커 전반에 대한 한글 자료 http://pyrasis.com/docker.html&lt;/p&gt;</content><author><name>이현민 lhm1442@gmail.com</name></author><category term="Docker" /><category term="AWS" /><summary type="html">Docker, AWS Codebuild, CodePipeline을 활용한 Ruby on Rails 개발과 배포</summary></entry></feed>