<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>구름을 채우다</title>
    <link>https://empty-cloud.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 25 Jun 2026 20:01:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>최성훈</managingEditor>
    <image>
      <title>구름을 채우다</title>
      <url>https://tistory1.daumcdn.net/tistory/3071520/attach/9e7748403c4344e58dc741b02e81dc1d</url>
      <link>https://empty-cloud.tistory.com</link>
    </image>
    <item>
      <title>파이썬 클린 코드 (5/10)</title>
      <link>https://empty-cloud.tistory.com/91</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5장. 데코레이터를 사용한 코드 개선&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;파이썬의 데코레이터&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1673785277084&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@modifier
def original(...):
	# ...&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데코레이터는 데코레이터 이후에 나오는 것을 데코레이터의 첫 번째 파라미터로 하고 데코레이터의 결과 값을 반환하게 하는 문법적 설탕(syntax sugar)일 뿐이다.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;... 예제에서 말하는 modifier는 파이썬 용어로 데코레이터라 하고, original을 데코레이팅된(decorated) 함수 또는 래핑된(wrapped) 객체라 한다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;함수 데코레이터&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f6e199;&quot;&gt;함수에 데코레이터를 사용하면 어떤 종류의 로직이라도 적용할 수 있다. 파라미터의 유효성을 검사하거나 사전조건을 검사하거나, 기능 전체를 새롭게 정의할 수도 있고, 서명을 변경할 수도 있고, 원래 함수의 결과를 캐시하는 등의 작업을 모두 할 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1673785876994&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ControlledException(Exception):
    &quot;&quot;&quot;도메인에서 발생하는 일반적인 예외&quot;&quot;&quot;


def retry(operation):
    @wraps(operation)
    def wrapped(*args, **kwargs):
    	last_raised = None
        RETRIES_LIMIT = 3
        for _ in range(RETRIES_LIMIT):  # 무시해도 되는 값은 '_'로 표현
            try:
                return operation(*args, **kwargs)
            except ControlledException as e:
                logger.info(&quot;retrying %s&quot;, operation.__qualname__)
                last_raised = e
        raise last_raised
    return wrapped&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 작성한 데코레이터는 파라미터가 없으므로 어떤 함수에도 적용이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673785957878&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@retry
def run_operation(task):
	&quot;&quot;&quot;실행 중 예외가 발생할 것으로 예상되는 특정 작업을 실행&quot;&quot;&quot;
    return task.run()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;여기서 &lt;b&gt;@retry&lt;/b&gt; 데코레이터는 실제로 파이썬에서 &lt;b&gt;run_operation = retry(run_operation)&lt;/b&gt;과 동일하게 실행하게 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, run_operation() 함수가 실제로 실행되기 전 @retry 데코레이터의 로직이 실행되고, @retry 데코레이터의 파라미터로 run_operation() 함수가 넘어가는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;클래스 데코레이터&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;함수에 적용한 것처럼 클래스에도 데코레이터를 사용할 수 있다. (PEP-3129). 유일한 차이점은 데코레이터 함수의 파라미터로 함수가 아닌 클래스를 받는다는 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f6e199;&quot;&gt;어떤 개발자들은 클래스 데코레이터가 복잡하고 가독성을 떨어뜨릴 수 있다고 말할 수 있다. 왜냐하면 클래스에서 정의한 속성과 메서드를 데코레이터 안에서 완전히 다른 용도로 변경할 수 있기 때문이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데코레이터를 남용할 경우 이것 또한 사실이다. 파이썬에서 보면 함수 데코레이터와 클래스 데코레이터는 다른 타입을 사용하는 것만 다를 뿐 차이점이 없다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  클래스 데코레이터는 코드 재사용과 DRY 원칙의 모든 이점을 공유한다. 클래스 데코레이터를 사용하면 여러 클래스가 특정 인터페이스나 기준을 따르도록 강제할 수 있다. 여러 클래스에 적용할 검사를 데코레이터에서 한 번만 하면 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  당장은 작고 간단한 클래스를 생성하고 나중에 데코레이터로 기능을 보강할 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  어떤 클래스에 대해서는 유지보수 시 데코레이터를 사용해 기존 로직을 훨씬 쉽게 변경할 수 있다. 메타클래스와 같은 방법을 사용해 보다 복잡하게 만드는 것은 주로 권장되지 않는다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 데코레이터가 DRY 원칙의 모든 이점을 공유한다는 점과, 가독성을 떨어뜨릴 수도 있다는 점에 모두 동의한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 데코레이터의 목적에 맞게 정확하게 사용하지 않으면 래핑된 객체(또는 함수)는 기존의 동작과 다르게 의도치 않게 동작할 수도 있으므로, 주의해서 사용하는 게 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673789774429&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class LoginEventSerializer:
    def __init__(self, event):
        self.event = event

    def serialize(self) -&amp;gt; dict:
        return {
            &quot;username&quot;: self.event.username,
            &quot;password&quot;: &quot;**민감한 정보 삭제**&quot;,
            &quot;ip&quot;: self.event.ip,
            &quot;timestamp&quot;: self.event.timestamp.strftime(&quot;%Y-%m-%d %H:%M&quot;),
        }


class LoginEvent:
    SERIALIZER = LoginEventSerializer

    def __init__(self, username, password, ip, timestamp):
        self.username = username
        self.password = password
        self.ip = ip
        self.timestamp = timestamp

        def serialize(self) -&amp;gt; dict:
            return self.SERIALIZER(self).serialize()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 LoginEventSerializer와 LoginEvent 클래스는 (1) password 필드를 숨기고, (2) timestamp 필드를 포매팅한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방법은 처음에는 잘 동작하지만, 시간이 지나면서 시스템을 확장할수록 다음과 같은 문제가 발생한다고 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;클래스가 너무 많아진다:&lt;/b&gt; 이벤트 클래스와 직렬화 클래스가 1:1로 맵핑되어 있으므로 직렬화 클래스가 점점 많아지게 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;이러한 방법은 충분히 유연하지 않다:&lt;/b&gt; 만약 password를 가진 다른 클래스에서도 이 필드를 숨기려면 함수로 분리한 다음 여러 클래스에서 호출해야 한다. 이는 코드를 충분히 재사용했다고 볼 수가 없다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;표준화:&lt;/b&gt; serialize() 메서드는 모든 이벤트 클래스에 있어야만 한다. 비록 믹스인을 사용해 다른 클래스로 분리할 수 있지만 상속을 제대로 사용했다고 볼 수 없다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 데코레이터의 대표적인 예를 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1673790647602&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from datetime import datetime


def hide_field(field) -&amp;gt; str:
    return &quot;**민감한 정보 삭제**&quot;


def format_time(field_timestamp: datetime) -&amp;gt; str:
    return field_timestamp.strftime(&quot;%Y-%m-%d %H:%M&quot;)


def show_original(event_field):
    return event_field


class EventSerializer:
    def __init__(self, serialization_fields: dict) -&amp;gt; None:
        self.serialization_fields = serialization_fields

    def serialize(self, event) -&amp;gt; dict:
        return {
            field: transformation(getattr(event, field))
            for field, transformation in self.serialization_fields.items()
        }


class Serialization:
    def __init__(self, **transformations):
        self.serializer = EventSerializer(transformations)

    def __call__(self, event_class):
        def serialize_method(event_instance):
            return self.serializer.serialize(event_instance)

        event_class.serialize = serialize_method
        return event_class


@Serialization(
    username=show_original, password=hide_field, ip=show_original, timestamp=format_time
)
class LoginEvent:
    def __init__(self, username, password, ip, timestamp):
        self.username = username
        self.password = password
        self.ip = ip
        self.timestamp = timestamp&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 첫 번째로 눈여겨봐야 할 점은 &lt;b&gt;LoginEvent&lt;/b&gt;에서 &lt;b&gt;SERIALIZER&lt;/b&gt; 속성이 사라지고, &lt;b&gt;@Serialization&lt;/b&gt; 데코레이터가 추가된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Serialization&lt;/b&gt; 데코레이터를 통해서 LoginEvent의 각 필드는 어떤 함수를 통해 직렬화할 것인지 쉽게 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;데코레이터에 인자 전달 - (1) 중첩 함수의 데코레이터&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;크게 보면 데코레이터는 함수를 파라미터로 받아서 함수를 반환하는 함수이다.&lt;/span&gt; 이런 함수를 고차 함수(higher-order function)라고 부른다. 실제로는 데코레이터의 본문에 정의된 함수가 호출된다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1673791611188&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;RETRIES_LIMIT = 3


class ControlledException(Exception):
    &quot;&quot;&quot;도메인에서 발생하는 일반적인 예외&quot;&quot;&quot;


def with_retry(retries_limit=RETRIES_LIMIT, allowed_exceptions=None):  # 데코레이터의 파라미터를 받는 함수
    allowed_exception = allowed_exceptions or (ControlledException,)

    def retry(operation):  # 데코레이터 로직을 수행하는 함수
        @wraps(operation)
        def wrapped(*args, **kwargs):  # 데코레이팅 된 결과를 반환 하는 함수
            last_raised = None
            for _ in range(RETRIES_LIMIT):  # 무시해도 되는 값은 '_'로 표현
                try:
                    return operation(*args, **kwargs)
                except ControlledException as e:
                    logger.info(&quot;retrying %s&quot;, operation.__qualname__)
                    last_raised = e
            raise last_raised

        return wrapped

    return retry&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서 말하는 것처럼 &lt;b&gt;@with_retry&lt;/b&gt; 데코레이터는 &lt;b&gt;retry&lt;/b&gt;라는 클로저를 반환한다. 즉, &lt;b&gt;@with_retry&lt;/b&gt; 데코레이터는 결과적으로 함수를 반환하는 함수인 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 데코레이터를 다른 함수에 적용한다면 다음과 같이 적용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1673791784150&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@with_retry()
# 또는 @with_retry(retries_limit=5)
# 또는 @with_retry(allowed_exceptions=(AttributeError,))
# 또는 @with_retry(retries_limit=5, allowed_exceptions=(ZeroDivisionError, AttributeError))
def run_operation(task):
    return task.run()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@with_retry&lt;/b&gt;&amp;nbsp;데코레이터는 내부적으로 &lt;b&gt;run_operation()&lt;/b&gt; 함수를 호출하고, 이 로직은 &lt;b&gt;wrapped()&lt;/b&gt; 클로저에서 구현돼 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;데코레이터에 인자 전달 - (2) 데코레이터 객체&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1673792507295&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;RETRIES_LIMIT = 3


class ControlledException(Exception):
    &quot;&quot;&quot;도메인에서 발생하는 일반적인 예외&quot;&quot;&quot;


class WithRetry:
    def __init__(self, retries_limit=RETRIES_LIMIT, allowed_exceptions=None):
        self.retries_limit = retries_limit
        self.allowed_exceptions = allowed_exceptions

    def __call__(self, operation):
        @wraps(operation)
        def wrapped(*args, **kwargs):
            last_raised = None
            for _ in range(self.retries_limit):
                try:
                    return operation(*args, **kwargs)
                except self.allowed_exceptions as e:
                    logger.info(&quot;retrying %s due to %s&quot;, operation, e)
                    last_raised = e
            raise last_raised

        return wrapped&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데코레이터 객체의 사용 방법은 이전 방법과 유사하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673793044274&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WithRetry(retries_limit=5)
def run_operation(task):
    return task.run()&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데코레이터와 DRY 원칙&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;모든 데코레이터, 특히 신중하게 설계되지 않은 데코레이터 코드는 코드의 복잡성을 증가시킨다. 어떤 사용자는 함수의 논리를 완전히 이해하기 위해 데코레이터의 경로를 따라가보길 원할 수 있다. 따라서 이 복잡성이 가치가 있어야 한다는 점을 기억하자. 그다지 재사용할 필요가 없을 경우 별개의 함수나 작은 클래스로도 충분한 경우가 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데코레이터 작성 시 가장 중요한 내용이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 데코레이터를 사용할 때, 그 내부 로직을 확인하지 않는 개발자는 거의 없을 것이다. (개발자는 데코레이터의 로직을 확인해야 하지만, 래핑 되는 함수의 입장에서는 데코레이터의 내부 로직을 알 필요가 없다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 예제에서 봤듯이 &lt;span&gt;데코레이터를 작성하게 되면&amp;nbsp;&lt;/span&gt;함수의 depth가 증가하고, 데코레이터의 내부 로직을 이해하는데 시간이 필요하다. 따라서 내가 작성하는 데코레이터가 단순히 코드 재사용성을 높이기 위해서인지, 아니면 기존의 함수(또는 객체)의 기능을 확장하기 위함인지 확인이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로는 단순 코드 재사용성을 높여서 DRY 원칙을 따르기 위함이라면, 데코레이터 말고 별도의 함수나 클래스로 추출하는 것이 더 나은 방법이라고 생각한다. retry 기능과 같이 래핑 할 함수의 기능은 그대로 유지하되, 기능 확장이 필요한 경우에 데코레이터를 사용하는 것이 좋지 않을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서 말하듯이, &lt;b&gt;내가 작성한 데코레이터의 복잡성이 가치가 있어야 한다&lt;/b&gt;는 점을 명심하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;좋은 데코레이터 분석&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;  &lt;b&gt;캡슐화와 관심사의 분리:&lt;/b&gt; 좋은 데코레이터는 실제로 하는 일과 데코레이팅하는 일의 책임을 명확히 구분해야 한다. 어설프게 추상화를 하면 안 된다. 즉 데코레이터의 클라이언트는 내부에서 어떻게 구현했는지 전혀 알 수 없는 블랙박스 모드로 동작해야 한다.&lt;br /&gt;  &lt;b&gt;독립성:&lt;/b&gt; 데코레이터가 하는 일은 독립적이어야 하며 데코레이팅되는 객체와 최대한 분리되어야 한다.&lt;br /&gt;  &lt;b&gt;재사용성:&lt;/b&gt; 데코레이터는 하나의 함수 인스턴스에만 적용되는 것이 아니라 여러 유형에 적용 가능한 형태가 바람직하다. 왜냐하면 하나의 함수에만 적용된다면 데코레이터가 아니라 함수로 대신할 수도 있기 때문이다. 충분히 범용적이어야 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 &lt;b&gt;@retry&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;데코레이터가 위에서 말하는 좋은 데코레이터의 대표적인 예일 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;위 특징과 &lt;b&gt;@retry&lt;/b&gt; 데코레이터를 하나씩 비교해 보면, @retry 데코레이터는 위에서 말하는 모든 특징들을 만족한다는 것을 알 수 있다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Books</category>
      <category>데코레이터</category>
      <category>클린 코드</category>
      <category>파이썬</category>
      <category>파이썬 클린 코드</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/91</guid>
      <comments>https://empty-cloud.tistory.com/91#entry91comment</comments>
      <pubDate>Mon, 16 Jan 2023 00:09:29 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 클린 코드 (4/10)</title>
      <link>https://empty-cloud.tistory.com/90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4장. SOLID 원칙&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;S:&lt;/b&gt; 단일 책임 원칙&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;O:&lt;/b&gt; 개방/폐쇄의 원칙&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;L:&lt;/b&gt; 리스코프(Liskov) 치환 원칙&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;I:&lt;/b&gt; 인터페이스 분리 원칙&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;D:&lt;/b&gt; 의존성 역전 원칙&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단일 책임 원칙 (S)&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;단일 책임 원칙(Single Responsibility Principle - SRP)&lt;/b&gt;은 소프트웨어 컴포넌트 (일반적으로 클래스)가 단 하나의 책임을 져야한다는 원칙이다. 클래스가 유일한 책임이 있다는 것은 하나의 구체적인 일을 담당한다는 것을 의미하며, 따라서 변화해야 할 이유는 단 하나뿐이다.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;도메인의 문제가 변경되면 클래스를 업데이트해야 한다. 다른 이유로 클래스를 수정해야 한다면 추상화가 잘못되어 클래스에 너무 많은 책임이 있다는 것을 뜻한다.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 말하는 도메인의 문제가 뭘까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다른 이유로 클래스를 수정해야 할 잘못된 예가 뭐가 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직은 추상적인 감밖에 잡히지 않네..  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;너무 많은 책임을 가진 클래스&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1651595573382&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class SystemMonitor:
    def load_activity(self):
        &quot;&quot;&quot;소스에서 처리할 이벤트를 가져오기&quot;&quot;&quot;
    
    def identify_events(self):
    	&quot;&quot;&quot;가져온 데이터를 파싱하여 도메인 객체 이벤트로 변환&quot;&quot;&quot;
    
    def stream_events(self):
        &quot;&quot;&quot;파싱한 이벤트를 외부 에이전트로 전송&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 클래스의 문제점은 독립적인 동작을 하는 메서드를 하나의 인터페이스에 정의했다는 것이다. 각각의 동작은 나머지 부분과 독립적으로 수행할 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 디자인 결함은 유지보수를 어렵게 하여 클래스가 경직되고 융통성 없으며 오류가 발생하기 쉽게 만든다. 이 예제에서 각 메서드는 클래스의 책임을 대표한다. 각각의 책임마다 수정 사유가 발생한다. 즉 메서드마다 다양한 변경의 필요성이 생기게 된다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 쉽게 말해서 &lt;b&gt;SytemMonitor&lt;/b&gt;라는 클래스는 이벤트를 (1) 로드하고 (2) 파싱하며 (3) 외부로 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 &lt;b&gt;SystemMonitor &lt;/b&gt;클래스의 책임이 너무 크다고 보는 것인데, 내 생각에는 &lt;i&gt;&quot;이벤트를 로드/파싱/전송하는 역할이 그렇게 큰 책임인가?&quot;&lt;/i&gt; 싶긴 하다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;책임 분산&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1651844327597&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class AlertSystem:
    def run(self):
        &quot;&quot;&quot;메소드 실행&quot;&quot;&quot;

class ActivityReader(AlertSystem):
    def load(self):
        &quot;&quot;&quot;소스에서 처리할 이벤트를 가져오기&quot;&quot;&quot;

class SystemMonitor(AlertSystem):
    def identify_event(self):
        &quot;&quot;&quot;가져온 데이터를 파싱하여 도메인 객체 이벤트로 변환&quot;&quot;&quot;

class Output(AlertSystem):
    def stream(self):
        &quot;&quot;&quot;파싱한 이벤트를 외부 에이전트로 전송&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;개방/폐쇄 원칙 (O)&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;개방/폐쇄 원칙(Open/Close Principle)&lt;/b&gt;은 모듈이 개방되어 있으면서도 폐쇄되어야 한다는 원칙이다(물론 다른 측면에서의 개방과 폐쇄이다).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클래스를 디자인할 때는 유지보수가 쉽도록 로직을 캡슐화하여 확장에는 개방되고 수정에는 폐쇄되도록 해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;간단히 말해서 확장 가능하고, 새로운 요구사항이나 도메인 변화에 잘 적응하는 코드를 작성해야 한다는 뜻이다. 즉 새로운 문제가 발생할 경우 새로운 것을 추가만 할 뿐 기존 코드는 그대로 유지해야 한다는 뜻이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f6e199;&quot;&gt;새로운 기능을 추가하다가 기존 코드를 수정했다면 그것은 기존 로직이 잘못 디자인되었다는 것을 뜻한다. 이상적으로는 요구사항이 변경되면 새로운 기능을 구현하기 위한 모듈만 확장을 하고 기존 코드는 수정을 하면 안 된다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;OCP 최종 정리&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;... &lt;span style=&quot;background-color: #f6e199;&quot;&gt;이 원칙은 &lt;b&gt;다형성&lt;/b&gt;의 효과적인 사용과 밀접하게 관련되어 있다&lt;/span&gt;. 다형성을 따르는 형태의 계약을 만들고 모델을 쉽게 확장할 수 있는 일반적인 구조로 디자인하는 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;... (중략)...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;마지막 중요한 요점은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;코드를 변경하지 않고 기능을 확장하기 위해서는 보호하려는 &lt;b&gt;추상화&lt;/b&gt;에 대해서 적절한 폐쇄를 해야 한다는 것이다&lt;/span&gt;.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음.. 이 부분을 읽다 보니 내가 짠 코드가 생각이 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일종의 보일러 플레이팅 된 함수인데, 새로운 요구사항이나 도메인 변화에 따라서 해당 함수를 고치려면 그 함수를 사용한 모든 코드를 수정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 내에서 워낙 많은 곳에서 쓰이다 보니 이제는 함부로 수정하기가 쉽지 않은데, 이 부분을 읽다 보니 내가 안티 패턴 코드를 작성한 것 같다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;리스코프 치환 법칙 (LSP)&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리스코프 치환 법칙(Liskov substitution principle, LSP)은 설계 시 안정성을 유지하기 위해 객체 타입이 유지해야하는 일련의 특성을 말한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;LSP의 주된 생각은 어떤 클래스에서든 클라이언트는 특별한 주의를 기울이지 않고도 하위 타입을 사용할 수 있어야 한다는 것이다. 어떤 하위 타입을 사용해도 실행에 따른 결과를 염려하지 않아야 한다. 즉, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;클라이언트는 완전히 분리되어 있으며 클래스 변경 사항과 독립되어야 한다&lt;/span&gt;.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;메서드 서명의 잘못된 데이터타입 검사&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1651846473450&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Event:
    ...
    def meets_condition(self, event_data: dict) -&amp;gt; bool:
        return False

class LoginEvent(Event):
    def meets_condition(self, event_data: list) -&amp;gt; bool:
        return bool(event_data)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LoginEvent&lt;/b&gt; 클래스의&amp;nbsp;&lt;b&gt;meet_condition()&lt;/b&gt; 메소드는 부모 클래스의 인자와 다르다. (dict &amp;lt;-&amp;gt; list)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스코프 치환 법칙에 따르면 &lt;b&gt;Event&lt;/b&gt; 객체와 &lt;b&gt;LoginEvent&lt;/b&gt; 객체의 호출자는 아무 변경 없이 두 개의 객체를 사용할 수 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 두 클래스의 &lt;b&gt;meets_condition()&lt;/b&gt; 인자가 서로 달라서 두 클래스 간의 다형성이 손상되고, 호출자는 서로 다른 방법으로 두 객체를 사용해야만 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 메소드 인자뿐만 아니라 반환값에서도 판단할 수 있는데, boolean 값이 아닌 다른 타입을 반환해도 문제가 발생한다. 리턴 타입을 boolean에서 다른 값으로 변경한다면, 계약(contract)을 위반하게 되고 이는 프로그램이 정상적으로 동작한다는 기대를 할 수 없게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;LSP 최종 정리&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;LSP&lt;/b&gt;는 객체지향 소프트웨어 설계의 핵심이 되는 다형성을 강조하기 때문에 좋은 디자인의 기초가 된다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;인터페이스의 메서드가 올바른 계층구조를 갖도록 하여 상속된 클래스가 부모 클래스와 다형성을 유지하도록 하는 것이다&lt;/span&gt;.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LSP를 지키지 않는다는 것은 부모 클래스의 계약과 호환되지 않는 확장을 한다는 것이므로 클라이언트와 계약이 깨지게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태에서 억지로 확장하려고 한다면 결과적으로 수정에 대해 폐쇄되어야 한다는 &lt;b&gt;개방/폐쇄 원칙(OCP)&lt;/b&gt;을 깨게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 &lt;b&gt;리스코프 치환 법칙(LSP)&lt;/b&gt;은 &lt;b&gt;개방/폐쇄 원칙(OCP)&lt;/b&gt;에 기여한다고 말할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인터페이스 분리 법칙&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;인터페이스 분리 원칙(Interface Segregation Principle, ISP)&lt;/b&gt;은 이미 반복적으로 재검토했던 &quot;작은 인터페이스&quot;에 대한 가이드라인을 제공한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이썬에서 인터페이스는 클래스 메서드의 형태를 보고 암시적으로 정의된다. 이것은 파이썬이 소위 말하는 &lt;b&gt;덕 타이핑(duck typing)&lt;/b&gt; 원리를 따르기 때문이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;... &lt;span style=&quot;background-color: #f6e199;&quot;&gt;즉 클래스의 유형, 이름 , docstring, 클래스 속성 또는 인스턴스 속성에 관계없이 객체의 본질을 정의하는 것은 궁극적으로 메서드의 형태이다.&lt;/span&gt; ..(중략)..&quot;어떤 새가 오리처럼 걷고 오리처럼 꽥꽥 소리를 낸다면 오리여야만 한다.&quot;는 데서 덕 타이핑이라고 불린다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬에 인터페이스가 없는 이유는 동적 바인딩 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java와 같은 컴파일 언어의 경우 클래스가 어떤 메소드를 가지고 있는지 미리 선언해야 하며, 이는 컴파일 타임에 체크된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에 파이썬의 경우엔 동적 바인딩 때문에 클래스와 관련된 속성들이 런타임에 체크된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 특징 때문에 파이썬은 덕 타이핑을 따를 수밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 파이썬의 인터페이스가 암시적으로 정의되는 이유는 덕 타이핑을 따르기 때문인 것처럼 말하는데, 그게 아니라 파이썬이 동적 언어이기 때문에 덕 타이핑을 따를 수밖에 없고, 결과적으로 클래스의 메소드 형태를 보고 판단할 수밖에 없게 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;추상적으로 말하자면 ISP는 다음을 뜻한다. 다중 메서드를 가진 인터페이스가 있다면 매우 정확하고 구체적인 구분에 따라 더 적은 수의 메서드(가급적이면 단 하나)를 가진 여러 개의 &lt;s&gt;메서드&lt;/s&gt;클래스로 분할하는 것이 좋다는 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 여러 개의 메서드로 분할하는 것이 좋다고 말하는데.. 이는 번역 오류인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드가 아니라 클래스가 아닐까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;SRP&lt;/b&gt;와 유사하지만 주요 차이점은 &lt;b&gt;ISP&lt;/b&gt;는 인터페이스에 대해 이야기하고 있다는 점이다. 따라서 이것은 행동의 추상화이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스 분리 법칙은 이 한 문장으로 요약할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;의존성 역전&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;의존성 역전 원칙(DIP)&lt;/b&gt;은 코드가 깨지거나 손상되는 취약점으로부터 보호해주는 흥미로운 디자인 원칙을 제시한다. 의존성을 역전시킨다는 것은 코드가 세부 사항이나 구체적인 구현에 적응하도록 하지 않고, 대신에 API같은 것에 적응하도록 하는 것이다.&lt;br /&gt;&lt;br /&gt;추상화를 통해 세부 사항에 의존하지 않도록 해야 하지만, 반대로 세부 사항 (구체적인 구현)은 추상화에 의존해야 한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 A 객체가 B 객체를 사용 중이라면, A 객체는 B 객체에 의존적이게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B 객체에 변경사항이 생긴다면 A 객체도 변경이 필요할 수 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 방지하기 위해 B 객체를 사용하기 위한 인터페이스(파이썬에서는 추상 클래스)를 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, A-B 클래스의 상호작용에서, A가 B에 의존적인 상황을 예방하기 위해 A-C-B와 같이 인터페이스를 두는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 A가 B에 의존하는 것이 아닌, B가 C 인터페이스를 따르게 한다고 볼 수 있다는 것이다.&lt;/p&gt;</description>
      <category>Books</category>
      <category>SOLID 원칙</category>
      <category>개방/폐쇄 원칙</category>
      <category>단일 책임 원칙</category>
      <category>리스코프 치환 법칙</category>
      <category>의존성 역전 원칙</category>
      <category>인터페이스 분리 법칙</category>
      <category>클린 코드</category>
      <category>파이썬</category>
      <category>파이썬 클린 코드</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/90</guid>
      <comments>https://empty-cloud.tistory.com/90#entry90comment</comments>
      <pubDate>Sat, 7 May 2022 02:59:05 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 클린 코드 (3/10)</title>
      <link>https://empty-cloud.tistory.com/89</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3장. 좋은 코드의 일반적인 특징&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;계약에 의한 디자인&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;계약에 의한 디자인(Design by Contract)&lt;/b&gt;이란 이런 것이다. 관계자가 기대하는 바를 암묵적으로 코드에 삽입하는 대신 양측이 동의하는 계약을 먼저 한 다음, 계약을 어겼을 경우는 명시적으로 왜 계속할 수 없는지 예외를 발생시키라는 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 책에서 말하는 계약은 소프트웨어 컴포넌트 간의 통신 중에 반드시 지켜져야 할 몇 가지 규칙을 강제하는 것이다. 계약은 주로 사전조건과 사후조건을 명시하지만 때로는 불변식과 부작용을 기술한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 말하는 계약이란 쉽게 말해 docstring과 같은 문서화를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 결과를 보장하기 위해 컴포넌트(함수, 메서드 등) 간 상호작용 중에 반드시 지켜야 할 규칙을 문서화하고, 이를 기반으로 컴포넌트의 동작을 검증하는 설계 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 계약(= 문서화)을 통해 각 컴포넌트의 동작을 명시하고, 이를 기반으로 설계를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;사전조건(precondition):&lt;/b&gt; 코드가 실행되기 전에 체크해야 하는 것들이다. 함수가 진행되기 전에 처리되어야 하는 모든 조건을 체크한다. 일반적으로 파라미터에 제공된 데이터의 유효성을 검사하지만 유효성 체크를 통해 부작용이 최소화된다는 점을 고려할 때 유효성 검사를 많이 하는 것이 좋다. 예를 들어 데이터베이스, 파일, 이전에 호출된 다른 메서드의 검사 등이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;이러한 작업은 호출자에게 부과된 임무이다.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;사후조건(postcondition):&lt;/b&gt; 사전조건과 반대로 여기서는 함수 반환 값의 유효성 검사가 수행된다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;사후조건 검증은 호출자가 이 컴포넌트에서 기대한 것을 제대로 받았는지 확인하기 위해 수행한다.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;불변식(invariant):&lt;/b&gt; 때로는 함수의 docstring에 불변식에 대해 문서화하는 것이 좋다. 불변식은 함수가 실행되는 동안에 일정하게 유지되는 것으로 함수의 로직에 문제가 없는지 확인하기 위한 것이다.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;부작용(side-effect):&lt;/b&gt; 선택적으로 코드의 부작용을 docstring에 언급하기도 한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 계약에 의한 디자인을 하는 이유는 오류가 발생할 때 쉽게 찾아낼 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불변식이나 부작용은 가능하다면 함께 작성하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 사전조건 검증에 실패한다면 이는 클라이언트의 결함(또는 실수)에 의한 것이고, 사후조건 검증에 실패한다면 사용된 모듈이나 클래스에 문제가 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사전조건의 경우엔 런타임에 확인할 수 있다는 것을 주의해야 한다. (잘 생각해보면 당연한 이유다.  )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 기회가 있을 때마다 docstring을 자세하게 작성하려고 하는데, 아래는 레거시 코드를 리팩토링 하면서 작성한 docstring이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P94Dz/btrvu1JzNMa/DB7yn5FbrmyclUOkoXvtfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P94Dz/btrvu1JzNMa/DB7yn5FbrmyclUOkoXvtfK/img.png&quot; data-alt=&quot;사전조건, 사후조건, 불변식이 포함된 docstring&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P94Dz/btrvu1JzNMa/DB7yn5FbrmyclUOkoXvtfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP94Dz%2Fbtrvu1JzNMa%2FDB7yn5FbrmyclUOkoXvtfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;688&quot; height=&quot;409&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사전조건, 사후조건, 불변식이 포함된 docstring&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zsmcc/btrvDhd3RB0/izRBjTXXokQeV7cMnD19g0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zsmcc/btrvDhd3RB0/izRBjTXXokQeV7cMnD19g0/img.png&quot; data-alt=&quot;사전조건, 사후조건, 부작용이 포함된 docstring&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zsmcc/btrvDhd3RB0/izRBjTXXokQeV7cMnD19g0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzsmcc%2FbtrvDhd3RB0%2FizRBjTXXokQeV7cMnD19g0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;683&quot; height=&quot;371&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사전조건, 사후조건, 부작용이 포함된 docstring&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 계약(= docstring)을 미리 작성한다면 함수의 책임을 사전에 명확하게 정의할 수 있는 장점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 오류가 발생한다면 함수를 호출한 곳에서 문제가 있는지, 함수 내부 로직상에 문제가 있는지 원인 분석에도 도움이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;사전조건(precondition)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 문제는 이 유효성 검사를 어디서 할지이다. 클라이언트가 함수를 호출하기 전에 모든 유효성 검사를 하도록 할 것인지, 함수가 자체적으로 로직을 실행하기 전에 검사하도록 할 것인지에 대한 문제이다. 전자는 관용적인(tolerant) 접근법이다. 왜냐하면 함수가 어떤 값이라도 (심지어 깨진 데이터도) 수용하기 때문이다. 반면 후자는 까다로운(demanding) 접근 방법에 해당한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f6e199;&quot;&gt;분석을 위해 DbC에 대한 까다로운 접근법을 사용해보자. 일반적으로 가장 안전하고 견고한 방법이며 업계에서도 가장 널리 쓰이는 방법이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음.. 나는 함수가 실행되는 가장 첫 부분에 유효성 검사(validation check)를 주로 넣는데, 운이 좋게도 올바른 방법이었구나 싶다. (함수 첫 부분에서 유효성 검사를 하는 이유는 딱히 없었고 그냥 그게 더 합리적으로 보였다. ㅋㅋ...  )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의해야 할 점이 있는데, 책에서는 다음과 같이 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떤 방식을 택하든 중복 제거 원칙을 항상 마음속에 간직해야 한다. 중복 제거 원칙은 사전조건 검증을 양쪽에서 하지 말고 오직 어느 한쪽에서만 해야 한다는 것이다. 즉, 검증 로직을 클라이언트에 두거나 함수 자체에 두어야 한다. 어떤 경우에도 중복해서는 안 된다. 이것은 뒤쪽에서 다룰 DRY 원칙과 관련이 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DRY 원칙이란 &lt;b&gt;&quot;Do Not Repeat Yourself&quot;&lt;/b&gt;를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 이미 있는 코드를 스스로 다시 짜지 말라는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 형태로든 중복된 로직을 제거하라는 의미이며, 사전조건을 검증할 때 &lt;b&gt;(1) 함수를 호출하는 곳, (2) 함수 내부&lt;/b&gt; 둘 중 한 곳에서만 검증을 하라는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DRY 원칙은 &lt;a href=&quot;https://docs.djangoproject.com/en/4.0/misc/design-philosophies/#don-t-repeat-yourself-dry&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Django의 설계 철학 중 하나&lt;/a&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;방어적(defensive) 프로그래밍&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;방어적 프로그래밍의 주요 주제는 예상할 수 있는 시나리오의 오류를 처리하는 방법과 (불가피한 조건에 의해서) 발생하지 않아야 하는 오류를 처리하는 방법에 대한 것이다. 전자는 에러 핸들링 프로시저에 대한 것이며, 후자는 어썰션(assertion)에 대한 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;예외처리&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;마지막으로 중요한 개념이 하나 더 있다. 예외는 대개 호출자에게 잘못을 알려주는 것이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;예외는 캡슐화를 약화시키기 때문에 신중하게 사용해야 한다.&lt;/span&gt; 함수에 예외가 많을수록 호출자가 호출하는 함수에 대해 더 많은 것을 알아야만 한다. 그리고 함수가 너무 많은 예외를 발생시키면 문맥에서 자유롭지 않다는 것을 의미한다. 왜냐하면 호출할 때마다 발생 가능한 부작용을 염두에 두고 문맥을 유지해야 하기 때문이다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꽤 공감되는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 함수 내부에서 발생시키는 예외가 많을수록, 함수를 호출하는 곳에서는 일어날 수 있는 예외 개수만큼 추가적인 예외처리를 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 이를 두고 &lt;b&gt;&quot;문맥을 유지&quot;&lt;/b&gt;한다라고 표현한 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면, 만약 아래와 같이 예외를 발생시킬 수 있는 something() 함수가 있다고 치자.&lt;/p&gt;
&lt;pre id=&quot;code_1647455836883&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;try:
	something()
except KeyError:
	handle_key_error()
except AttributeError:
	handle_attribute_error()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;something()을 호출하는 곳에서는 something()이 어떤 예외를 일으키는지 알고 있어야 하며, 만약 발생할 수 있는 예외가 누락된다면 프로그램에 장애를 유발할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 예외가 많아질수록 책에서는 다음과 같이 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이것은 함수가 응집력이 약하고 너무 많은 책임을 가지고 있다는 것을 알기 위한 경험적 확인 방법이 될 수도 있다. 예외가 너무 많이 발생하면 여러 개의 작은 것으로 나눠야한다는 신호일 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;관심사의 분리&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;소프트웨어에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;관심사를 분리하는 목표는 파급 효과를 최소화하여 유지보수성을 향상시키는 것&lt;/span&gt;이다. 파급(ripple) 효과는 어느 지점에서의 변화가 전체로 전파되는 것을 의미한다. 이러한 오류나 예외는 다른 예외를 유발하거나 혹은 먼 지점의 결함을 초래한다. 함수 정의를 약간만 변경해도 코드의 여러 부분에 영향을 미쳐 많은 코드를 변경해야 할 수도 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음.. 요즘 내가 고민하고 있는 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 함수의 리턴 값을 dict에서 tuple로 변경하고 싶은데, 이 함수를 호출하는 부분이 너무 많다 보니 함부로 변경하기가 어렵다는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1647458021605&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def something():
    a = do_something()
    return a&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수를&lt;/p&gt;
&lt;pre id=&quot;code_1647458051648&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def something():
    a = do_something()
    b = do_something_else()
    return a, b&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 변경하고 싶지만, 그렇게 하려면 something()의 리턴값을 사용하는 모든 부분을 수정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 방법은 없을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;개발 지침 약어&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;DRY/OAOO&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;DRY(Do not Repeat Yourself)&lt;/b&gt;와 &lt;b&gt;OAOO(Once and Only Once)&lt;/b&gt;는 밀접한 관련이 있으므로 함께 다룬다. 자명한 원리로써 중복을 반드시 피해야 한다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;YAGNI&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;YAGNI(You Ain't Gonna Need it)&lt;/b&gt;는 과잉 엔지니어링을 하지 않기 위해 솔루션 작성 시 계속 염두에 두어야 하는 원칙이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장성을 고려한다면 가끔씩 고도화된 설계가 필요할 때가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 &lt;b&gt;&quot;오직 현재의 요구사항을 잘 해결하기 위한 소프트웨어를 작성하고 가능한 나중에 수정하기 쉽도록 작성하는 것이다.&quot;&lt;/b&gt;라고 했는데, 이는 &lt;b&gt;'지금 당장은 일단 구현만 하면 되겠네'&lt;/b&gt;같은 오해의 소지를 불러일으킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가령 내가 어떤 요구사항을 구현하기 위해서 &lt;b&gt;(1) DB에 칼럼을 추가할 것인지, (2) 스키마를 정규화할 것인지&lt;/b&gt; 고민한다고 가정해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 나는 아래와 같은 경우를 두고 고민을 할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DB에 단순히 칼럼만 추가했는데 더 복잡한 요구사항이 발생하는 경우 (예: 정규화)&lt;/li&gt;
&lt;li&gt;스키마를 정규화했는데 추가 요구사항이 없는 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 성향 차이겠지만, 난 2번을 선호한다.&lt;br /&gt;(즉, 일단 정규화를 한다는 뜻이다.   )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번과 같은 방법으로 계속 코드를 작성한다면, 언젠가는 돌이킬 수 없는 코드가 될 수도 있다고 생각하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만 다른 누군가는 &lt;b&gt;'굳이 지금 필요하지도 않은데 일을 더 크게 벌려야 하나?'&lt;/b&gt;라고 생각할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난 아직도 정답을 잘 모르겠지만, 책에서는 다음과 같이 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다시 말해 디자인을 할 때 내린 결정으로 특별한 제약 없이 개발을 계속할 수 있다면, 굳이 필요 없는 추가 개발을 하지 말라는 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;KIS&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;KIS(Keep It Simple)&lt;/b&gt;는 이전 원칙과 매우 흡사하다. 소프트웨어 컴포넌트를 설계할 때 과잉 엔지니어링을 피해야 한다. 선택한 솔루션이 문제에 적합한 최소한의 솔루션인지 자문해보자.&lt;br /&gt;&lt;br /&gt;..(중략).. 기억해야 할 점은 디자인이 단순할수록 유지 관리가 쉽다는 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 책에서는 디자인을 단순하게 유지하라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KIS&lt;/b&gt;에서 말하는 것을 보니, 코드 구조를 단순하게 유지하라는 말인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 디자인 패턴과 같은 거시적 관점에서의 설계를 생각했는데, 예제 코드를 보아하니 그저 코드를 단순하게 짜라는 말인 것 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1647535616616&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ComplicatedNamespace:
    ACCEPTED_VALUES = (&quot;id_&quot;, &quot;user&quot;, &quot;location&quot;)

    @classmethod
    def init_with_data(cls, **data):
        instance = cls()
        for key, value in data.items():
            if key in cls.ACCEPTED_VALUES:
                setattr(instance, key, value)
        return instance&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 아래와 같이 단순하게 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 초기화하기 위해서 반복문과 setattr()을 사용 중인데, 굳이 이렇게 작성할 필요가 없다는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1647535681805&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ComplicatedNamespace2:
    ACCEPTED_VALUES = (&quot;id_&quot;, &quot;user&quot;, &quot;location&quot;)

    def __init__(self, **data):
        accepted_data = {
            k: v for k, v in data.items() if k in self.ACCEPTED_VALUES
        }
        self.__dict__.update(accepted_data)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이썬의 철학을 기억하자: 단순한 것이 복잡한 것보다 낫다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컴포지션과 상속&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상속은 강력한 개념이지만 위험도 있다. 가장 주된 위험은 부모 클래스를 확장하여 새로운 클래스를 만들 때마다 부모와 강력하게 결합된 새로운 클래스가 생긴다는 점이다. 이미 설명했듯이 소프트웨어를 설계할 때마다 결합력(coupling)을 최소한으로 줄이는 것이 중요하다.&lt;br /&gt;&lt;br /&gt;..(중략).. 코드를 재사용하는 올바른 방법은 여러 상황에서 동작 가능하고 쉽게 조합할 수 있는 응집력 높은 객체를 사용하는 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;상속이 좋은 선택인 경우&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파생 클래스를 만드는 것은 양날의 검이 될 수 있으므로 주의해야 한다. 한편으로는 부모 클래스의 메서드를 공짜로 전수 받을 수 있는 장점이 있지만 그러나 다른 한편으로 모든 것을 새로운 클래스로 가져왔기 때문에 새로운 정의에 너무 많은 기능을 추가하게 되는 단점도 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맞는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 클래스가 부모 클래스를 상속한다면 부모 클래스의 모든 것(속성, 메소드)을 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 자식 클래스에서 확장하는 범위가 적고, 자식 클래스가 부모 클래스의 메소드를 100% 활용하지 않는다면 이는 올바르지 않은(혹은 불필요한) 상속이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 그렇다면 자식 클래스가 확장하는 범위가 적절한지, 부모 클래스가 너무 많은 책임을 가지고 있는 건 아닌지 다시 확인해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;믹스인(mixin)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;믹스인은 코드를 재사용하기 위해 일반적인 행동을 캡슐화해놓은 기본 클래스이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;일반적으로 믹스인 클래스는 그 자체로는 유용하지 않으며 대부분이 크래스에 정의된 메서드나 속성에 의존하기 때문에 이 클래스만 확장해서는 확실히 동작하지 않는다.&lt;/span&gt; 보통은 다른 클래스와 함께 믹스인 클래스를 &lt;b&gt;다중 상속&lt;/b&gt;하여 믹스인에 있는 메서드나 속성을 사용한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;믹스인은 활용도가 높은 유용한 클래스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;믹스인 클래스가 어떤 클래스인지는 예제를 통해서 이해하는 게 더 쉽다.&lt;/p&gt;
&lt;pre id=&quot;code_1647543096495&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class BaseTokenizer:
    &quot;&quot;&quot;하이픈(-)을 기준으로 문자열을 나눈다.&quot;&quot;&quot;
    def __init__(self, str_token):
        self.str_token = str_token

    def __iter__(self):
        yield from self.str_token.split(&quot;-&quot;)


class UpperIterableMixin:
    &quot;&quot;&quot;부모 클래스의 __iter__() 결과를 대문자로 변환한다.&quot;&quot;&quot;
    def __iter__(self):
        return map(str.upper, super().__iter__())


class Tokenizer(UpperIterableMixin, BaseTokenizer):
    &quot;&quot;&quot;믹스인에서 __iter__()를 호출하고 super()를 통해 BaseTokenizer에 위임한다.&quot;&quot;&quot;
    pass&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 아래와 같이 실행된다.&lt;/p&gt;
&lt;pre id=&quot;code_1647543144489&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; tk = Tokenizer(&quot;a-b-c-d-e&quot;)
&amp;gt;&amp;gt;&amp;gt; list(tk)
['A', 'B', 'C', 'D', 'E']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;함수와 메서드의 인자&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인자는 함수에 어떻게 복사되는가&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이썬의 첫 번째 규칙은 모든 인자가 값에 의해 전달(passed by a value)된다는 것이다. 즉 함수에 값을 전달하면 함수의 서명에 있는 변수에 할당하고 나중에 사용한다. 인자를 변경하는 함수는 인자의 타입에 따라 다른 결과를 낼 수 있다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;만약 변경 가능한(mutable) 객체를 전달하고 함수에서 값을 변경하면 함수 반환 시 실제 값이 변경되는 부작용이 생길 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 흔한 실수가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;파이썬에서 함수 기본 인자는 함수가 호출되는 순간마다가 아니라&lt;b&gt; 함수가 정의되는 순간에(한 번)만 평가&lt;/b&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 만약 함수의 기본 인자가 변경 가능한(mutable)한 객체로 선언된다면 이후에 함수가 호출될 때마다 그 객체를 참조한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1647544755280&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def append_to(element, to=[]):
    to.append(element)
    return to&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647544869341&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; first_list = append_to(12)
&amp;gt;&amp;gt;&amp;gt; first_list
[12]
&amp;gt;&amp;gt;&amp;gt; second_list = append_to(42)
&amp;gt;&amp;gt;&amp;gt; second_list  # [42]가 나오길 기대한다.
[12, 42]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #3e4349;&quot;&gt;리스트 객체는 append() 함수가 정의될 때 한 번만 생성되고, 이후에 모든 append() 호출에 &lt;span style=&quot;background-color: #ffffff; color: #3e4349;&quot;&gt;똑같은 리스트 객체가&lt;/span&gt;&amp;nbsp;참조된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #3e4349;&quot;&gt;이를 방지하기 위해 우리는 함수의 기본 인자로 변경 가능한(mutable)한 객체를 사용하지 않고, 다음과 같이 사용해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647545168889&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def append_to(element, to=None):
    if not to:
        to = []
    to.append(element)
    return to&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Books</category>
      <category>Clean Code</category>
      <category>DBC</category>
      <category>Design by Contract</category>
      <category>Dry</category>
      <category>OAOO</category>
      <category>Python</category>
      <category>YAGNI</category>
      <category>클린 코드</category>
      <category>파이썬</category>
      <category>파이썬 클린 코드</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/89</guid>
      <comments>https://empty-cloud.tistory.com/89#entry89comment</comments>
      <pubDate>Fri, 18 Mar 2022 04:49:17 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 클린 코드 (2/10)</title>
      <link>https://empty-cloud.tistory.com/88</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2장. 파이썬스러운(Pythonic) 코드&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인덱스와 슬라이스&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;.. 만약 래퍼도 아니고 내장(builtin) 객체를 사용하지도 않은 경우는 자신만의 &lt;b&gt;시퀀스&lt;/b&gt;를 구현할 수 있다. 이때는 다음 사항에 유의해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &amp;nbsp; 범위로 인덱싱하는 결과는 해당 클래스와 같은 타입의 인스턴스여야 한다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &amp;nbsp; slice에 의해 제공된 범위는 파이썬이 하는 것처럼 마지막 요소는 제외해야 한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 말하는 &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;시퀀스(sequence)&lt;/a&gt;란 기본적으로 &lt;b&gt;list, tuple, range&lt;/b&gt; 객체를 의미한다. (이외에 다른 시퀀스 타입도 존재한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컨텍스트 관리자 (Context Manager)&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;컨텍스트 관리자&lt;/b&gt;는 파이썬이 제공하는 유용한 기능이다. 이것이 특별히 유용한 이유는 패턴에 잘 대응되기 때문이다. 이 패턴은 사실상 모든 코드에 적용될 수 있으며 사전조건과 사후조건을 가지고 있다. 즉 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;주요 동작의 전후에 작업을 실행하려고 할 때 유용하다.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;일반적으로 리소스 관리와 관련하여 컨텍스트 관리자를 자주 볼 수 있다.&lt;/span&gt; 예를 들어 일단 파일을 열면 파일 디스크립터 누수를 막기 위해 작업이 끝나면 적절히 닫히길 기대한다. 또는 서비스나 소켓에 대한 연결을 열었을 때도 적절하게 닫거나 임시 파일을 제거하는 등의 작업을 해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 모든 경우에 일반적으로 할당된 모든 리소스를 해제해야 한다. 모든 것이 잘 처리되었을 경우의 해제는 쉽지만 예외가 발생하거나 오류를 처리해야 하는 경우는 어떻게 될까? ..(중략).. 가장 일반적인 방법은 finally 블록에 정리 코드를 넣는 것이다. 예를 들어 다음과 같은 간단한 예제를 생각해볼 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1645981165276&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fd = open(filename)
try:
    process_file(fd)
finally:
    fd.close()&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇지만 똑같은 기능을 매우 우아하고 파이썬스러운 방법으로 구현할 수도 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1645981217157&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;with open(filename) as fd:
    process_file(fd)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;with&lt;/b&gt;문은 컨텍스트 관리자로 진입하게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컨텍스트 관리자&lt;/b&gt;&lt;span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;__enter__()&lt;/b&gt;&lt;span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;__exit__()&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 개의 매직 메서드로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;with&lt;span&gt;&amp;nbsp;&lt;/span&gt;블록이 실행되기 전에&lt;span&gt;&amp;nbsp;&lt;/span&gt;__enter__()&lt;span&gt;&amp;nbsp;메소드를&lt;/span&gt; 실행하고 그 반환값은&amp;nbsp;&lt;b&gt;as&lt;/b&gt;로 지정된 변수에 저장되며(__enter__() 메소드가 꼭 값을 반환할 필요는 없다.), with 블록이 끝날 때는&lt;span&gt;&amp;nbsp;&lt;/span&gt;__exit__()&lt;span&gt;&amp;nbsp;메소드가&lt;/span&gt; 호출된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서&amp;nbsp;&lt;b&gt;open()&lt;/b&gt;은 컨텍스트 관리자 프로토콜을 구현하며, 예외가 발생한 경우에도 파일(fd)이 자동으로 닫힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f6e199;&quot;&gt;컨텍스트 관리자는 관심사를 분리하고 독립적으로 유지되어야하는 코드를 분리하는 좋은 방법이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프로퍼티, 속성과 객체 메서드의 다른 타입들&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;public, private, protected 프로퍼티를 가지는 다른 언어들과는 다르게 파이썬 객체의 모든 프로퍼티와 함수는 &lt;b&gt;public&lt;/b&gt;이다.&lt;/span&gt; 즉 호출자가 객체의 속성을 호출하지 못하도록 할 방법이 없다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;엄격한 강제사항은 없지만 몇 가지 규칙이 있다. 밑줄로 시작하는 속성은 해당 객체에 대해 private을 의미하며, 외부에서 호출하지 않기를 기대하는 것이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;다시 말하지만 이것을 금지하는 것은 아니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2년 넘게 파이썬만 쓰다 보니 접근제어자(Access Modifier)가 있는 자바는 어떻게 사용하는지 까먹은 것 같다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬의 모든 프로퍼티와 함수가 public인 것은 프로젝트 내 어디서든 프로퍼티/함수에 접근이 가능하므로 비즈니스 로직을 구현할 때는 매우 편하지만, 반대로 코드 퀄리티를 신경 쓰지 않으면 스파게티 코드가 돼버리는 단점이 있는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히나 &lt;b&gt;_&lt;/b&gt;의&amp;nbsp;경우는 언어에서 강제하는 것이 아니기 때문에 (우리 팀에 한에서는) 실무에서 잘 쓰지 않는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음엔 신경 써서 잘 활용해봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;밑줄 두 개를 사용하면 실제로 파이썬은 다른 이름을 만든다. &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;이름 맹글링(name mangling)이라 한다. 이것이 하는 일은 다음과 같은 이름의 속성을 만드는 것이다. &quot;_&amp;lt;class-name&amp;gt;__&amp;lt;attribute-name&amp;gt;&quot;&lt;/span&gt;&lt;/b&gt; 경우 '_Connector__timeout'이라는 속성이 만들어지며 이러한 속성은 다음과 같이 접근하여 수정할 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1645985645707&quot; class=&quot;pycon ruby&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; vars(conn)
{'source': 'postgresql://localhost', '_Connector__timeout': 60}
&amp;gt;&amp;gt;&amp;gt; conn._Connector__timeout
60
&amp;gt;&amp;gt;&amp;gt; conn._Connector__timeout = 30
&amp;gt;&amp;gt;&amp;gt; conn.connect()
connecting with 30s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중 밑줄은 파이썬스러운(pythonic) 코드가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속성을 private으로 정의하려는 경우 하나의 밑줄을 사용하고 파이썬스러운 관습을 지키자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로퍼티는 &lt;b&gt;명령-쿼리 분리 원칙(Command and Query Separation - CC08)&lt;/b&gt;을 따르기 위한 좋은 방법이다. 명령-쿼리 분리 원칙은 객체의 메서드가 무언가의 상태를 변경하는 커맨드이거나 무언가의 값을 반환하는 쿼리이거나 둘 중에 하나만 수행해야지 둘 다 동시에 수행하면 안 된다는 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Get/Set의 성격을 띠는 메소드는 철저하게 로직을 분리하라는 뜻인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이터러블 객체&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;... 객체를 반복할 수 있는지 확인하기 위해 파이썬은 고수준에서 다음 두 가지를 차례로 검사한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &amp;nbsp; 객체가 &lt;b&gt;__next__&lt;/b&gt;나 &lt;b&gt;__iter__&lt;/b&gt; 이터레이터 메서드 중 하나를 포함하는지 여부&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &amp;nbsp; 객체가 시퀀스이고 &lt;b&gt;__len__&lt;/b&gt;과 &lt;b&gt;__getitem__&lt;/b&gt;을 모두 가졌는지 여부&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이터러블을 사용하면 메모리를 적게 사용하지만 n 번째 요소를 얻기 위한 시간복잡도는 O(n)이다. 하지만 시퀀스로 구현하면 더 많은 메모리가 사용되지만 (모든 것을 한 번에 보관해야 하므로) 특정 요소를 가져오기 위한 인덱싱의 시간 복잡도는 O(1)로 상수에 가능하다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컨테이너 객체&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨테이너는 &lt;b&gt;__contains__&lt;/b&gt; 메서드를 구현한 객체로 __contains__ 메서드는 일반적으로 Boolean 값을 반환한다. 이 메서드는 파이썬에서 in 키워드가 발견될 때 호출된다.&lt;br /&gt;&lt;br /&gt;.. (중략) ..&lt;br /&gt;&lt;br /&gt;이 메서드를 잘 사용하면 코드의 가독성이 정말 높아진다. (파이썬스러운 코드다!)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;__contains__&lt;/b&gt;와 같은 매직 메서드를 구현하려면 클래스가 있어야 하는데, 현재 실무에서는 특별히 클래스를 따로 작성하지 않고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Django 프레임워크 내부적으로 &lt;b&gt;모델-시리얼라이저-뷰 레이어&lt;/b&gt;를 두고 코드를 작성하기 때문에, 별도의 매직메서드를&amp;nbsp; 위한 새로운 클래스를 작성할 필요가 딱히 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Django에서 지원하는 클래스(모델, 시리얼라이저, 뷰)만으로도 대부분의 비즈니스 로직은 구현 가능하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Django도 &lt;b&gt;MVT(Model-View-Template)&lt;/b&gt;라는&lt;span&gt;&amp;nbsp;MVC 패턴과&amp;nbsp;&lt;/span&gt;유사한 패턴을 가지고 있는데, MVC와 마찬가지로 &lt;b&gt;Fat Model Skinny View&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fat Model Skinny View를 지향한다면, 파이썬 매직 메서드를 모델 클래스 안에다가 구현하면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음.. 지금 돌이켜보니 요즘엔 비즈니스 로직을 View 레이어 근처에다가 구현했던 것 같은데, 다시 주의하면서 코드를 짜야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Books</category>
      <category>Clean Code</category>
      <category>Python</category>
      <category>클린 코드</category>
      <category>파이썬</category>
      <category>파이썬 클린 코드</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/88</guid>
      <comments>https://empty-cloud.tistory.com/88#entry88comment</comments>
      <pubDate>Fri, 4 Mar 2022 05:31:51 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 클린 코드 (1/10)</title>
      <link>https://empty-cloud.tistory.com/87</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1장.&amp;nbsp; 코드 포맷팅과 도구&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;클린 코드의 중요성&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드의 품질을 관리하지 않는다면 결과적으로 기술 부채가 누적되어 실패한 프로젝트가 될 가능성이 높아진다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클린 코드인지 아닌지는 다른 엔지니어가 코드를 읽고 유지 관리할 수 있는지 여부에 달려있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 상당히 공감하는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클린 코드 판단은 &lt;span&gt;내 코드 리뷰에서도&lt;/span&gt; 이루어지는데, 내 코드가 꼼꼼하지 않게 승인돼도 큰 상관이 없다.&lt;br /&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;리뷰를 받는 코드의 maintainer는 나 자신(=코드 작성자)이기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 대부분의 개발자는 은퇴할 때까지 한 곳에서만 일하지 않기 때문에, 내가 이직을 한다면 내 동료는 내가 작성한 코드를 유지보수해야만 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 팀을 떠날 때의 maintainer는 내 동료이며, 내 코드에 대한 평가는 이때에도 이루어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;클린 코드를 위해서는 내가 알아볼 수 있는 코드가 아니라 동료도 알아볼 수 있는 코드를 작성해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;좋은 코드 레이아웃에서 가장 필요한 특성은 일관성이다. 코드가 일관되게 구조화되어 있으면 가독성이 높아지고 이해하기 쉬워진다. 만약 팀원 모두가 코드의 일관성을 유지하지 않고 자신의 방식으로 일을 하고 있다면 결국은 많은 시간과 노력을 투입해야만 할 것이다. 오류가 발생하기 쉽고 이해하기 어렵거나 애매한 부분이 많이 생기게 된다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 개인적으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;팀원 모두 노력이 필요하다고 생각한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 유틸리티성 모듈의 이름을 정할 때 &lt;b&gt;common&lt;/b&gt;, &lt;b&gt;shared&lt;/b&gt;, 혹은 &lt;b&gt;utilities&lt;/b&gt;라고 정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 공통 모듈임에도 불구하고 만약 여러 동료가 각기 다른 이름으로 모듈을 생성/관리한다면, 그 모듈은 책에서 말하듯이 이해하기 어렵거나 애매한 모듈이 돼버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적인 생각으로는 비슷한 일이 발생할 때는&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;팀원에게 의견을 구하고, 프로젝트 내 일관성을 유지하기 위해 의견을 통일해야 하지 않을까 싶다.&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Docstring과 어노테이션&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드에 주석(Comment)을 다는 것은 여러 가지 이유로 나쁜 습관이다. 첫째, 주석은 코드로 아이디어를 제대로 표현하지 못했음을 나타내는 것이다. 만약 무언가를 왜 어떻게 하는지 꼭 설명해야 한다면 그 코드는 아마도 충분히 좋지 못한 것이다. 둘째, &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;..(중략)..&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그러나 docstring의 경우는 좀 다르다. 다시 말하지만 주석을 다는 것이 아니라 코드의 특정 컴포넌트(모듈, 클래스, 메서드 또는 함수)에 대한 문서화이다. 이런 컴포넌트에 사용하는 것은 허용될 뿐 아니라 권장되는 부분이다. 가능한 많은 docstring을 추가하는 것이 좋다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주석(Comment)&lt;/b&gt;과 &lt;b&gt;docstring&lt;/b&gt;의 차이를 이해하는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;특히 파이썬은 동적으로 타입을 결정하기 때문에 함수나 메서드를 거치면 변수나 객체의 값이 무엇인지 알기가 어려운 경우가 많다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 docstring을 통해 해당 컴포넌트에 대한 설명이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;... 코드를 변경한 경우 위키(wiki), 사용자 매뉴얼, README 파일 또는 docstring 등 관련된 모든 내용을 업데이트하는 것이 중요하다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.. 고 하지만 막상 실제로 업무를 진행하다 보면 다 챙기는 것은 불가능에 가까운 것 같다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;동료가 작성한 코드를 살펴볼 때는 다음 질문을 해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이 코드를 동료 개발자가 쉽게 이해하고 따라갈 수 있을까?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  업무 도메인에 대해서 말하고 있는가?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  팀에 새로 합류하는 사람도 쉽게 이해하고 효과적으로 작업할 수 있을까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 습관적으로 위와 같은 고민을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 고민 자체가 습관이 되다 보니 비록 코드를 짜기까지 시간이 걸리기도 하고, 코드 리뷰를 하면서 변수명이나 로직 자체에 대해서 의견을 제시하는 경우가 많다. (그냥 의견을 제시하는 것뿐이지만, 가끔씩 동료는 내가 딴지를 건다고 느끼는 것 같다.  )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 보이지는 않지만 동료의 감정을 상하게 만든 것 같이 느껴질 때가 있다.&lt;br /&gt;(제 소프트 스킬이 부족한 탓입니다.. 동료분들께 다시 한번 사과드립니다  &amp;zwj;♂️ &amp;zwj;♂️)&lt;br /&gt;&lt;br /&gt;그래도 이 부분을 읽으니 내가 가진 습관이 꼭 나쁜 습관은 아닌 것 같아서 조금이나마 위로가 된다.&lt;/p&gt;</description>
      <category>Books</category>
      <category>Clean Code</category>
      <category>Python</category>
      <category>클린 코드</category>
      <category>파이썬</category>
      <category>파이썬 클린 코드</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/87</guid>
      <comments>https://empty-cloud.tistory.com/87#entry87comment</comments>
      <pubDate>Fri, 4 Mar 2022 05:31:30 +0900</pubDate>
    </item>
    <item>
      <title>Code Formatter와 Linter의 차이</title>
      <link>https://empty-cloud.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Formatter:&lt;/b&gt; 코드 스타일을 수정함 (예: spacing, 줄바꿈, 주석 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linter:&lt;/b&gt; 에러를 찾기 위해 코드를 분석하고, 더 나은 코드 퀄리티를 위한 모범 사례를 제공함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Formatter&lt;/b&gt;의 예는 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;a = [first_element, second_element, third_element, forth_element, fifth_element, sixth_element]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가 아래와 같이 변경된다.&lt;/p&gt;
&lt;pre id=&quot;code_1645905922833&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a = [
  first_element,
  second_element,
  third_element,
  forth_element,
  fifth_element,
  sixth_element
]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linter&lt;/b&gt;의 예는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1645906544216&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type(a) is list&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가 아래와 같이 변경된다.&lt;/p&gt;
&lt;pre id=&quot;code_1645906574000&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;isinstance(a, list)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 이상적인 사용 사례는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Formatter&lt;/b&gt;로 코드 스타일을 수정(또는 통일)하고&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Linter&lt;/b&gt;로 발생할 수 있는 에러를 수정하거나 더 나은 구문을 사용한다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>TIL</category>
      <category>formatter</category>
      <category>Linter</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/86</guid>
      <comments>https://empty-cloud.tistory.com/86#entry86comment</comments>
      <pubDate>Fri, 4 Mar 2022 05:31:09 +0900</pubDate>
    </item>
    <item>
      <title>Django ORM의 Case-Sensitive 검색 (MySQL)</title>
      <link>https://empty-cloud.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;얼마전 동료에게 CS(Customer Service) 문의가 들어왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A 유저가 투표한 내용이 B 유저에게 노출이 됐다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 보기엔 꽤나 흥미롭고 귀찮은 이슈였는데( ), 동료가 분석한 원인은 다음과 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;A가 '홍길동'에게 투표했음&lt;/li&gt;
&lt;li&gt;A의 고유 ID는 &lt;b&gt;ABCDE&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;B의 고유 ID는 &lt;b&gt;ABcdE (대소문자만 다름)&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Django 서버는 DB 설정에 따라서 대소문자를 구별함 (&lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/charset-collation-implementations.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;utf8_general_ci&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Django ORM &lt;a href=&quot;https://docs.djangoproject.com/en/4.0/ref/models/querysets/#filter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;filter()&lt;/b&gt;&lt;/a&gt;를 통해 case-sensitive한 쿼리(&lt;a href=&quot;https://docs.djangoproject.com/en/3.1/ref/models/querysets/#exact&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;__exact__&lt;/b&gt;&lt;/a&gt; field lookup)를 보내도, DB에서 case-insensitive하게 처리&lt;/li&gt;
&lt;li&gt;DB에서 case-insensitive하게 처리하므로 A와 B는 동일한 사용자로 판단&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 &lt;b&gt;MySQL&lt;/b&gt;의 collation이 &lt;b&gt;utf8_general_ci&lt;/b&gt;로 설정돼있어서 생긴 문제였다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Non-UCA collations have a one-to-one mapping from character code to weight. In MySQL, such collations are case-insensitive and accent-insensitive.&amp;nbsp;utf8_general_ci&amp;nbsp;is an example:&amp;nbsp;'a',&amp;nbsp;'A',&amp;nbsp;'&amp;Agrave;', and&amp;nbsp;'&amp;aacute;'&amp;nbsp;each have different character codes but all have a weight of&amp;nbsp;0x0041&amp;nbsp;and compare as equal.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;utf8_general_ci&lt;/b&gt;는 case-insenstive하며 accent-insensitive하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름에서 알 수 있듯이, &lt;b&gt;_ci&lt;/b&gt;는 case-insensitive를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;collation에 대한 네이밍 컨벤션은 &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/charset-collation-names.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;에 나와있으며, 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;258&quot;&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/charset-collation-names.html&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cw8BDZ/btrupJbUrjy/8pyE7562VKLXxKQbAiRylk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcw8BDZ%2FbtrupJbUrjy%2F8pyE7562VKLXxKQbAiRylk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;298&quot; height=&quot;258&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;Collation 접미사 의미&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제일 근본적인 해결법은 DB 설정을 &lt;b&gt;utf8mb4_bin&lt;/b&gt;과 같은 case-sensitive한&amp;nbsp;&lt;span&gt;collation&lt;/span&gt;으로 바꾸는 것이겠지만, DB 설정을 바꾸는 일은 DBA에게 승인을 받아야 하기 때문에 대응까지 시간이 걸린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 개발자 입장에서 빠른 대응이 필요하다면 &lt;span&gt;코드 배포로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;쿼리에 &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/charset-collate.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;COLLATE&lt;/a&gt;를 추가하는 것도 방법일 듯 하다.&lt;/p&gt;</description>
      <category>Server Framework/Django</category>
      <category>Case Sensitive</category>
      <category>django</category>
      <category>mysql</category>
      <category>ORM</category>
      <category>utf8mb4_bin</category>
      <category>utf8_general_ci</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/85</guid>
      <comments>https://empty-cloud.tistory.com/85#entry85comment</comments>
      <pubDate>Fri, 4 Mar 2022 05:30:04 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] 컨테이너 외부로 노출하기 (docker0, veth)</title>
      <link>https://empty-cloud.tistory.com/84</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;네트워크 인터페이스 (Network Interface)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;네트워크 인터페이스&lt;/span&gt;&lt;/b&gt;는 존재할 수 있는 모든 네트워크 어댑터에 대한 지속적 인터페이스를 IP 계층에 제공하기 위해 네트워크 고유 장치 드라이버 및 IP 계층과 통신하는 네트워크 고유 소프트웨어입니다. 또한, &lt;u&gt;네트워크 인터페이스에는 네트워크 주소가 있습니다&lt;/u&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;가상 머신과 마찬가지로 도커 컨테이너 또한 가상 IP를 할당받는데요, &lt;u&gt;기본적으로 도커는 &lt;b&gt;172.17.0.xxx&lt;/b&gt;의 IP 주소를 순차적으로 컨테이너에게 할당합니다&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;먼저, 호스트의 네트워크 인터페이스를 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN2G4U/btqESgcdfcE/yRWNf6vQ6NkADPRo5zy8Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN2G4U/btqESgcdfcE/yRWNf6vQ6NkADPRo5zy8Sk/img.png&quot; data-alt=&quot;내 노트북의 네트워크 인터페이스 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN2G4U/btqESgcdfcE/yRWNf6vQ6NkADPRo5zy8Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN2G4U%2FbtqESgcdfcE%2FyRWNf6vQ6NkADPRo5zy8Sk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내 노트북의 네트워크 인터페이스 목록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;여기서 우리는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;docker0&lt;/b&gt;&lt;/span&gt;라는 네트워크 인터페이스를 확인할 수 있는데요, docker0는 실제 네트워크 어댑터가 연결되어있지 않은 가상의 리눅스 브릿지로, IP주소 &lt;b&gt;172.17.0.1/16&lt;/b&gt;로 지정되어 있습니다. 또한 호스트의 IP 주소는 &lt;b&gt;111.13.113.181&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;도커 서버는 리눅스 커널 내에서 컨테이너가 다른 컨테이너 또는 외부와 통신하기 위해 사용되는 이더넷 브릿지로서 호스트 시스템의 &lt;b&gt;docker0&lt;/b&gt; 인터페이스를 생성하고 구성합니다&lt;/span&gt;. docker0 브릿지는 도커에 의해서 생성된 가상 인터페이스로, RFC1918에 의해 정의된 호스트 머신에서 사용하지 않는 범위 내에서 임의로 주소와 서브넷을 선택하여 docker0로 할당합니다. 모든 도커 컨테이너는 기본적으로 docker0로 연결되며, docker0에 연결된 컨테이너는 외부와 통신하기 위해 도커가 생성한 iptables NAT 규칙을 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;이제 컨테이너를 하나 생성하고, 그 컨테이너의 네트워크 인터페이스를 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x6d0H/btqERQ5TWXR/w1gtMdNmWVJFDOef8xAuAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x6d0H/btqERQ5TWXR/w1gtMdNmWVJFDOef8xAuAK/img.png&quot; data-alt=&quot;임의로 생성한 컨테이너의 네트워크 인터페이스 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x6d0H/btqERQ5TWXR/w1gtMdNmWVJFDOef8xAuAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx6d0H%2FbtqERQ5TWXR%2Fw1gtMdNmWVJFDOef8xAuAK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;임의로 생성한 컨테이너의 네트워크 인터페이스 목록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;생성된 컨테이너는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;eth0&lt;/b&gt;&lt;/span&gt;라는 네트워크 인터페이스를 가지며, IP 주소는 &lt;b&gt;172.17.0.2/16&lt;/b&gt;인 것을 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;포트 바인딩 (Port Bindnig)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;아무런 설정을 하지 않았다면, 우리가 생성한 컨테이너는 외부에서 접근할 수 없으며, 도커 엔진이 설치된 호스트에서만 접근할 수 있습니다. 이 컨테이너를 외부에 노출시키기 위해서는 먼저 호스트와 연결이 되어야 합니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;이를 위해서 우리는&amp;nbsp;&lt;b&gt;eth0&lt;/b&gt;의 IP와 포트 번호를 호스트의 IP와 포트 번호에 바인딩해야 합니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;다음의 명령어로 컨테이너를 실행하고, 아파치 웹서버를 설치합니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ docker run -i -t --name network_test -p 9999:80 ubuntu:14.04
root@57db86df07c5:/# apt install apache2 -y
root@57db86df07c5:/# service apache2 start&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;여기서 눈여겨 볼 점은, &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;-p 9999:80&lt;/span&gt;&lt;/b&gt; 부분입니다. -p 옵션의 입력형식은 다음과 같습니다.&lt;/p&gt;
&lt;blockquote style=&quot;text-align: center;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;-p [바인딩 할 호스트의 포트]:[바인딩 할 컨테이너의 포트]&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;만약 호스트의 9999 포트 번호와 컨테이너의 80 포트 번호로 올바르게 바인딩이 되었다면, 다음 그림처럼 나타낼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1bOGu/btqETCeDj5Q/y6UmsBShAojHD61ihY1JJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1bOGu/btqETCeDj5Q/y6UmsBShAojHD61ihY1JJ0/img.png&quot; data-alt=&quot;바인딩 된 컨테이너&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1bOGu/btqETCeDj5Q/y6UmsBShAojHD61ihY1JJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1bOGu%2FbtqETCeDj5Q%2Fy6UmsBShAojHD61ihY1JJ0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바인딩 된 컨테이너&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이제 올바르게 바인딩 되었는지 확인해봅시다. &lt;u&gt;호스트의 IP 주소인 &lt;b&gt;110.13.113.181&lt;/b&gt;와 바인딩 된 포트번호인 &lt;b&gt;9999&lt;/b&gt;를 사용하여 웹 브라우저에서 접속합니다&lt;/u&gt;. (물론 호스트에서 접속해야 합니다.) 만약 컨테이너가 &lt;span style=&quot;color: #333333;&quot;&gt;올바르게 바인딩 되어&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;호스트와 연결이 되었다면, 아파치 웹 페이지가 보일 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rAMhN/btqEQtw3ome/klGIAkikqr9aZtyzmVK7VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rAMhN/btqEQtw3ome/klGIAkikqr9aZtyzmVK7VK/img.png&quot; data-alt=&quot;아파치 웹 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rAMhN/btqEQtw3ome/klGIAkikqr9aZtyzmVK7VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrAMhN%2FbtqEQtw3ome%2FklGIAkikqr9aZtyzmVK7VK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아파치 웹 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;호스트에서 9999 포트로 접속했을 때 아파치 웹 페이지가 보이네요! 이제 우리는 컨테이너가 호스트와 연결된 것을 확인했습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;veth 인터페이스 (veth Interface)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;앞서 우리는&amp;nbsp;성공적으로&amp;nbsp;호스트와 컨테이너를 연결했습니다. 하지만 어떻게 컨테이너와 호스트가 연결되었는지 아직 잘 모릅니다.&lt;/p&gt;
&lt;p&gt;다시 한 번 컨테이너와 호스트의 네트워크 인터페이스를 확인해봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sF6tM/btqESpmunXY/gaYpkEKj2ghDlnYJrOFAwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sF6tM/btqESpmunXY/gaYpkEKj2ghDlnYJrOFAwk/img.png&quot; data-alt=&quot;컨테이너와 호스트의 네트워크 인터페이스 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sF6tM/btqESpmunXY/gaYpkEKj2ghDlnYJrOFAwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsF6tM%2FbtqESpmunXY%2FgaYpkEKj2ghDlnYJrOFAwk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;컨테이너와 호스트의 네트워크 인터페이스 목록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;아니 이게 뭔가요? 아파치 서버를 설치하여 테스트 하는 동안, 우리가 모르는 사이 &lt;u&gt;&lt;b&gt;vethcf10e95&lt;/b&gt;라는 네트워크 인터페이스가 추가되었습니다&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;외부와 연결을 해야할 경우, 도커 데몬은&amp;nbsp;호스트 머신에 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;veth&lt;/b&gt;&lt;/span&gt;라는 네트워크 인터페이스를 생성합니다. 생성된 veth 인터페이스는 호스트의 &lt;b&gt;docker0&lt;/b&gt; 브릿지에 바인딩됩니다.&lt;/span&gt; 컨테이너는 자신이 가진 &lt;b&gt;eth0&lt;/b&gt; 인터페이스와 &lt;b&gt;docker0&lt;/b&gt; 브릿지에 바인딩 된 &lt;b&gt;veth&lt;/b&gt;&amp;nbsp;인터페이스를 통해 &lt;b&gt;docker0&lt;/b&gt; 브릿지와 연결이 됩니다. 이를 통해 결론적으로 컨테이너는 외부와 통신을 할 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;따라서 현재 제 노트북에서 컨테이너와 연결된 네트워크 인터페이스는 다음 그림과 같이 나타낼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2PbKr/btqETLwoV8S/c44iJwmgYFu8YDwQNunhCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2PbKr/btqETLwoV8S/c44iJwmgYFu8YDwQNunhCk/img.png&quot; data-alt=&quot;바인딩 된 컨테이너&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2PbKr/btqETLwoV8S/c44iJwmgYFu8YDwQNunhCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2PbKr%2FbtqETLwoV8S%2Fc44iJwmgYFu8YDwQNunhCk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바인딩 된 컨테이너&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;References&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;본 포스트는 다음의 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ibm.com/support/knowledgecenter/ko/ssw_aix_71/network/tcpip_interfaces.html&quot;&gt;https://www.ibm.com/support/knowledgecenter/ko/ssw_aix_71/network/tcpip_interfaces.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.ibm.com/recipes/tutorials/networking-your-docker-containers-using-docker0-bridge/&quot;&gt;https://developer.ibm.com/recipes/tutorials/networking-your-docker-containers-using-docker0-bridge/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rancher.com/learning-paths/introduction-to-container-networking/&quot;&gt;https://rancher.com/learning-paths/introduction-to-container-networking/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Docker</category>
      <category>docker</category>
      <category>docker0</category>
      <category>Network Interface</category>
      <category>veth</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/84</guid>
      <comments>https://empty-cloud.tistory.com/84#entry84comment</comments>
      <pubDate>Tue, 16 Jun 2020 04:12:19 +0900</pubDate>
    </item>
    <item>
      <title>#2</title>
      <link>https://empty-cloud.tistory.com/83</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;IMG_4242.jpg&quot; data-origin-width=&quot;5989&quot; data-origin-height=&quot;3993&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDyBo7/btqENZhRABz/UG2fkLhoKkoslwl0153pX1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDyBo7/btqENZhRABz/UG2fkLhoKkoslwl0153pX1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDyBo7/btqENZhRABz/UG2fkLhoKkoslwl0153pX1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDyBo7%2FbtqENZhRABz%2FUG2fkLhoKkoslwl0153pX1%2Fimg.jpg&quot; data-filename=&quot;IMG_4242.jpg&quot; data-origin-width=&quot;5989&quot; data-origin-height=&quot;3993&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;도전&lt;/p&gt;</description>
      <category>나만의 사진전</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/83</guid>
      <comments>https://empty-cloud.tistory.com/83#entry83comment</comments>
      <pubDate>Fri, 12 Jun 2020 17:54:31 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] Ubuntu 18.04 도커 엔진(Docker Engine) 설치하기</title>
      <link>https://empty-cloud.tistory.com/82</link>
      <description>&lt;p&gt;본 포스트 이후 모든 글은 Ubuntu 18.04를 기준으로 포스팅할 예정이니 참고 바랍니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 전제조건 (Prerequisites)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;도커 엔진을 설치하기 위해서는 다음 우분투 버전 중 64비트 버전이 필요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ubuntu Focal 20.04 (LTS)&lt;/li&gt;
&lt;li&gt;Ubuntu Eoan 19.10&lt;/li&gt;
&lt;li&gt;Ubuntu Bionic 18.04 (LTS)&lt;/li&gt;
&lt;li&gt;Ubuntu Xenial 16.04 (LTS)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이전 버전 설치 제거하기&lt;/h3&gt;
&lt;p&gt;도커의 이전 버전들은 &lt;b&gt;docker&lt;/b&gt;, &lt;b&gt;docker.io&lt;/b&gt; 또는 &lt;b&gt;docker-engine&lt;/b&gt;으로 불립니다. 만약 이 버전들이 설치되어 있다면 삭제하시면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo apt-get remove docker docker-engine docker.io containerd runc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;만약 &lt;b&gt;apt-get&lt;/b&gt; 명령어가 아무 패키지도 설치되어 있지 않다고 해도 문제는 없습니다.&lt;/p&gt;
&lt;p&gt;이전 버전을 삭제하더라도 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;/var/lib/docker/&lt;/span&gt; 경로에 이미지, 컨테이너, 볼륨 그리고 네트워크를 포함한 내용은 보존됩니다. 이제 도커 엔진은 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;docker-ce&lt;/span&gt;&lt;/b&gt;로 불립니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;도커 엔진 설치하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치 방법&lt;/h3&gt;
&lt;p&gt;우리는 도커 엔진을 우리가 원하는 방법에 따라 다르게 설치할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대부분의 사용자들은 쉬운 설치와 업그레이드 작업을 위해 &lt;b&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;도커의 레포지토리를 설정&lt;/a&gt;하고, 그 레포지토리로부터 설치&lt;/b&gt;합니다. 이 방법이 권장되는 방법입니다.&lt;/li&gt;
&lt;li&gt;몇몇 사용자들은 &lt;b&gt;데비안 패키지(DEB)를 다운로드하고 &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;수동으로 도커 엔진을 설치&lt;/a&gt;하고, 완전히 수동으로 업그레이드를 관리&lt;/b&gt;합니다. 이 방법은 물리적으로 인터넷 접근이 불가능한 에어갭 시스템에 도커를 설치하는 것과 같은 상황에서 유용합니다.&lt;/li&gt;
&lt;li&gt;테스트 환경과 개발 환경에서 사용자들은 도커 엔진을 설치하기 위해 &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;자동화된 편리한 스크립트를 사용&lt;/b&gt;&lt;/a&gt;하는 것을 선택할 수도 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;저는 첫 번째 방법으로 도커 엔진을 설치하도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레포지토리를 사용하여 설치하기&lt;/h3&gt;
&lt;p&gt;새로운 호스트 머신에 도커 엔진을 처음 설치하기 전에, 도커 레포지토리를 설정해야 합니다. 그다음에 우리는 그 레포지토리로부터 도커를 설치하고 업데이트할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;레포지토리 설정하기&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;apt&lt;/b&gt; 패키지 인덱스를 업데이트하고, &lt;b&gt;apt&lt;/b&gt;가 HTTPS를 통해 레포지토리를 사용하기 위한 패키지를 설치합니다.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;도커의 공식 GPG 키를 추가합니다.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo apt-get update
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -&lt;/code&gt;&lt;/pre&gt;
fingerprint의 마지막 8자리를 검색해서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88&lt;/span&gt;의 fingerprint를 가진 키를 가졌다는 것을 확인합니다.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo apt-key fingerprint 0EBFCD88

pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) &amp;lt;docker@docker.com&amp;gt;
sub   rsa4096 2017-02-22 [S]&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;stable&lt;/b&gt; 레포지토리를 설정하기 위해 다음의 명령어를 사용하세요. &lt;b&gt;nightly&lt;/b&gt;나 &lt;b&gt;test&lt;/b&gt; 레포지토리를 추가하기 위해서는, 아래 명령어에서 &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;stable&lt;/span&gt;&lt;/b&gt; 단어 뒤에 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;nightly&lt;/b&gt;&lt;/span&gt; 또는 &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;test&lt;/span&gt;&lt;/b&gt;를 추가하세요.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;주의:&lt;/b&gt;&lt;/span&gt; 아래의 &lt;b&gt;lsb_release -cs&lt;/b&gt; 명령어는 &lt;b&gt;xenial&lt;/b&gt;과 같은 우분투 배포 버전의 이름을 반환합니다. 가끔 Linux Mint와 같은 배포 버전에서는 &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;$(lsb_release -cs)&lt;/span&gt;&lt;/b&gt; 부분을 부모 우분투 배포 버전으로 변경해야 합니다. 예를 들면, 만약 우리가 &lt;b&gt;Linux Mint Tessa&lt;/b&gt;를 사용하고 있다면 &lt;b&gt;bionic&lt;/b&gt;을 사용할 수 있습니다. 도커는 테스트하지 않거나 지원하지 않는 우분투 배포 버전에 대해서는 아무 보장도 하지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo add-apt-repository &quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;도커 엔진 설치하기&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;apt&lt;/b&gt; 패키지 인덱스를 업데이트하고, 가장 최신 버전의 도커 엔진과 containerd를 설치하세요. 특정 버전을 설치하려면 다음 단계로 넘어가세요.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;특정 버전의 도커 엔진을 설치하기 위해, 레포지토리 내에 있는 설치 가능한 버전을 선택하고 설치하세요.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ apt-cache madison docker-ce

  docker-ce | 5:18.09.1~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  docker-ce | 5:18.09.0~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  docker-ce | 18.06.1~ce~3-0~ubuntu       | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  docker-ce | 18.06.0~ce~3-0~ubuntu       | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;두 번째 열의 문자열을 사용해서 특정 버전을 설치하세요, 예를 들면 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;5:18.09.1~3-0~ubuntu-xenial&lt;/b&gt;&lt;/span&gt;이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo apt-get install docker-ce= docker-ce-cli= containerd.io&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;hellow-world&lt;/b&gt;&lt;/span&gt; 이미지를 실행해서 도커 엔진이 정상적으로 설치되었는지 확인합니다.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo docker run hello-world&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 명령어는 테스트 이미지를 다운로드하고 컨테이너 내에서 실행시킵니다. 컨테이너가 실행될 때, 정보를 나타내는 메시지가 출력되고 종료됩니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이제 도커 엔진이 설치되고 실행 중입니다. 도커를 설치하면서 &lt;i&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;docker&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;라는 사용자 그룹이 생성되었지만 어떤 사용자도 추가되지 않았습니다. 따라서 우리는 도커 명령어를 실행하기 위해 &lt;b&gt;sudo&lt;/b&gt; 명령어를 사용해야 합니다&lt;/span&gt;&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Non-root 사용자로서 도커 관리하기&lt;/h4&gt;
&lt;p&gt;도커 데몬은 TCP 포트 대신에 Unix 소켓으로 바인딩합니다. 기본적으로 &lt;b&gt;root&lt;/b&gt; 사용자가 Unix 소켓을 소유하고 있고, 다른 사용자들은 &lt;b&gt;sudo&lt;/b&gt; 명령어를 사용해야만 접근할 수 있습니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;도커 데몬은 항상 &lt;b&gt;root&lt;/b&gt; 사용자로서 실행됩니다&lt;/i&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;만약 &lt;b&gt;sudo&lt;/b&gt; 명령어를 덧붙여서 도커 명령어를 실행하는 게 귀찮으시다면, &lt;b&gt;docker&lt;/b&gt;라는 Unix 그룹을 생성하고 사용자를 추가하면 됩니다. 도커 데몬이 시작될 때, 도커 데몬은 &lt;b&gt;docker&lt;/b&gt; 사용자 그룹의 사용자에 의해서 접근할 수 있는 Unix 소켓을 생성합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;도커 사용자 그룹은 &lt;b&gt;root&lt;/b&gt; 사용자와 동일한 권한을 갖습니다. 시스템에 어떤 영향을 끼치는지 확인하려면 &lt;a href=&quot;https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 참조하세요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;docker&lt;/b&gt; 사용자 그룹을 생성합니다. (사용자 그룹이 존재하지 않는 경우)
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo groupadd docker&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;현재 사용자를 &lt;b&gt;docker&lt;/b&gt; 그룹에 추가합니다.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo usermod -aG docker $USER&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;그룹 사용자의 멤버 권한을 갱신하기 위해 로그아웃 후 다시 접속합니다.&lt;br /&gt;만약 VM에서 테스트 중이라면, 변경 사항을 적용하기 위해 VM을 재부팅해야 할 수도 있습니다.&lt;br /&gt;X Windows와 같은 데스크톱 리눅스 환경의 경우, 세션을 완전히 종료하고 다시 로그인하세요.&lt;br /&gt;리눅스의 경우, 사용자 그룹에 변경사항을 적용하기 위해 다음의 명령어를 사용할 수 있습니다.&lt;br /&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ newgrp docker&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;sudo&lt;/b&gt; 명령어 없이 도커 명령어가 실행되는지 실행합니다.
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ docker run hello-world&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;만약 현재 사용자를 &lt;b&gt;docker&lt;/b&gt; 그룹에 추가하기 전에 &lt;b&gt;sudo&lt;/b&gt; 명령어를 사용해서 도커 명령어를 실행했다면, 아마 다음의 에러를 볼 수도 있습니다. 이 에러는 &lt;b&gt;~/.docker/&lt;/b&gt; 경로가 &lt;b&gt;sudo&lt;/b&gt; 명령어로 인해 잘못된 권한으로 생성되었다는 것을 의미합니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;WARNING: Error loading config file: /home/user/.docker/config.json -
stat /home/user/.docker/config.json: permission denied&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 문제를 해결하기 위해, &lt;b&gt;~/.docker/&lt;/b&gt; 디렉터리를 삭제하거나(디렉터리는 자동으로 다시 생성되지만, 개인 변경사항들은 모두 잃어버립니다), 다음의 명령어로 해당 디렉터리의 소유자와 권한을 변경합니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo chown &quot;$USER&quot;:&quot;$USER&quot; /home/&quot;$USER&quot;/.docker -R
$ sudo chmod g+rwx &quot;$HOME/.docker&quot; -R&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;References&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;본 포스트는 다음 주소를 참조하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot;&gt;https://docs.docker.com/engine/install/ubuntu/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Docker</category>
      <category>docker</category>
      <category>Installation</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/82</guid>
      <comments>https://empty-cloud.tistory.com/82#entry82comment</comments>
      <pubDate>Mon, 8 Jun 2020 03:11:28 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] 도커란?</title>
      <link>https://empty-cloud.tistory.com/81</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;도커란?&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;도커(Docker)는 리눅스 컨테이너에 여러 기능을 추가함으로써 애플리케이션을 컨테이너로서 조금 더 쉽게 사용할 수 있게 만들어진 오프소스 프로젝트이다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Go&lt;/b&gt;&lt;/span&gt; 언어로 작성돼 있으며, 2013년 3월에 처음 발표된 이후 지금까지 꾸준히 개발되고 있다.&lt;/p&gt;
&lt;p&gt;일반적으로 도커라 함은, 도커 엔진(Docker Engine) 또는 도커에 관련된 모든 프로젝트를 의미하지만, 도커 엔진이라는 의미로 더 많이 사용된다. (&lt;span style=&quot;color: #9d9d9d;&quot;&gt;도커 엔진은 컨테이너를 생성하고 관리하는 주체로서, 그 자체로도 컨테이너를 제어할 수 있고 다양한 기능을 제공하는 도커의 주 프로젝트이기 때문&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컨테이너(Container) vs. 가상 머신(Virtual Machine)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;컨테이너와 가상 머신은 호스트 운영체제(Host OS) 위에서 가상화를 통한 격리 환경을 구성한다는 공통점이 있다.&lt;/p&gt;
&lt;p&gt;하지만 격리 환경을 구성하기 위해 기술적인 차이가 있다. 두 가상화 기술의 차이점을 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJInTo/btqEGgJDou9/G0r60gxnCRzq2XSsXxW4wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJInTo/btqEGgJDou9/G0r60gxnCRzq2XSsXxW4wk/img.png&quot; data-alt=&quot;좌: 컨테이너, 우: 가상머신&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJInTo/btqEGgJDou9/G0r60gxnCRzq2XSsXxW4wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJInTo%2FbtqEGgJDou9%2FG0r60gxnCRzq2XSsXxW4wk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;좌: 컨테이너, 우: 가상머신&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨테이너 (Container)&lt;/h3&gt;
&lt;p&gt;컨테이너는 코드와 그 종속성들을 함께 패키징 하는 &lt;b&gt;애플리케이션 계층의 추상화&lt;/b&gt;이다. 여러 컨테이너가 동일한 시스템에서 실행될 수 있고 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;OS 커널을 다른 컨테이너와 공유할 수 있으며, 각각은 사용자 공간에서 격리된 프로세스로 실행&lt;/i&gt;&lt;/span&gt;된다. 컨테이너는 VM보다 더 적은 공간을 차지하며(&lt;span style=&quot;color: #9d9d9d;&quot;&gt;컨테이너 이미지의 크기는 일반적으로 수십 MB이다&lt;/span&gt;), 더 많은 애플리케이션을 처리할 수 있고, 더 적은 VM과 운영체제를 요구한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가상 머신 (Virtual Machine)&lt;/h3&gt;
&lt;p&gt;가상 머신(이하 VM)은 &lt;b&gt;물리적 하드웨어를 추상화&lt;/b&gt;하여 한 개의 서버를 여러 서버로 전환하는 것이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;하이퍼바이저(Hypervisor)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;i&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;를 통해 단일 시스템에서 여러 VM을 실행할 수 있다&lt;/span&gt;&lt;/i&gt;. 각 VM에는 운영체제, 애플리케이션, 필수적인 이진 파일과 라이브러리가 포함되며, 이는 수십 GB를 차지한다. VM은 부팅 속도 또한 느릴 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;위는 도커 공식 홈페이지에서 발췌하고 번역한 내용이다.&lt;/p&gt;
&lt;p&gt;위의 설명만 읽었을 때에는 컨테이너와 가상 머신의 가장 큰 차이점은 &lt;u&gt;애플리케이션의 경량화&lt;/u&gt;와 &lt;u&gt;디스크 용량뿐이라고&lt;/u&gt; 느껴진다.&lt;/p&gt;
&lt;p&gt;하지만 그뿐만 아니라, 컨테이너를 사용함으로써 다음과 같은 장점을 가질 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;일관된 환경&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너는 &lt;i&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;호스트 OS 위에서 실행되는 격리된 공간&lt;/span&gt;&lt;/i&gt;이다. 따라서 컨테이너 자체에 특별한 권한을 주지 않는 이상, 컨테이너 내부의 작업은 호스트 OS에 영향을 끼치지 않는다. 즉, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;호스트 OS에는 일관된 환경을, 컨테이너에는 독립된 환경을 보장받을 수 있다&lt;/i&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;애플리케이션의 독립성 및 확장성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 서비스는 여러 모듈이 상호작용하는 로직을 포함하고 있으며, 모든 로직을 하나의 프로그램에서 실행하는 것을 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;모놀리틱 애플리케이션(Monolithic Application)&lt;/span&gt;&lt;/b&gt;이라고 한다. &lt;i&gt;모놀리틱 애플리케이션은 &lt;span style=&quot;color: #ee2323;&quot;&gt;서비스가 복잡해지고 커질수록 애플리케이션 자체의 확장성과 유연성이 줄어든다&lt;/span&gt;&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;이러한 단점을 해결하기 위한 개념이 바로 &lt;b&gt;마이크로서비스(Microservice)&lt;/b&gt; 구조이다. 마이크로서비스는 여러 모듈을 독립된 형태로 구성하기 때문에 언어에 종속되지 않고, &lt;i&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;빠르고 쉽게 모듈을 관리하고 확장할 수 있다는 장점&lt;/span&gt;&lt;/i&gt;이 있다. 컨테이너는 빠른 시간 내에 생성 및 실행이 가능하며, &lt;i&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;여러 모듈에게 독립적인 환경을 동시에 제공&lt;/span&gt;&lt;/i&gt;할 수 있기 때문에 마이크로서비스 구조에서 가장 많이 사용되는 가상화 기술이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2W295/btqEGC60d8K/5fPlMGp1SwudWpGvurJHZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2W295/btqEGC60d8K/5fPlMGp1SwudWpGvurJHZ1/img.png&quot; data-alt=&quot;좌: 모놀리틱 애플리케이션, 우: 마이크로서비스&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2W295/btqEGC60d8K/5fPlMGp1SwudWpGvurJHZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2W295%2FbtqEGC60d8K%2F5fPlMGp1SwudWpGvurJHZ1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;좌: 모놀리틱 애플리케이션, 우: 마이크로서비스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;References&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;a href=&quot;https://www.docker.com/resources/what-container&quot;&gt;https://www.docker.com/resources/what-container&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Docker</category>
      <category>container</category>
      <category>docker</category>
      <category>hypervisor</category>
      <category>Virtual machine</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/81</guid>
      <comments>https://empty-cloud.tistory.com/81#entry81comment</comments>
      <pubDate>Sat, 6 Jun 2020 02:05:41 +0900</pubDate>
    </item>
    <item>
      <title>[백준 2309번] 일곱 난쟁이</title>
      <link>https://empty-cloud.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2309&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btEIu6/btqBZgTlnSA/eW5DH0Y7tfft5P7QEb4xsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btEIu6/btqBZgTlnSA/eW5DH0Y7tfft5P7QEb4xsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btEIu6/btqBZgTlnSA/eW5DH0Y7tfft5P7QEb4xsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtEIu6%2FbtqBZgTlnSA%2FeW5DH0Y7tfft5P7QEb4xsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1142&quot; height=&quot;73&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more79_0&quot; data-id=&quot;79_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content79_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less79_0&quot; data-id=&quot;79_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;브루트 포스&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;문제에서 의도하는 바는 9명의 난쟁이 중 키의 합이 100이 되는 7명의 난쟁이를 고르는 것이다. (가능한 경우의 수가 여러 개일 경우 한 가지만 출력한다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이제 &lt;span style=&quot;color: #333333;&quot;&gt;웬만한 &lt;/span&gt;브루트 포스 문제는 막힘없이 풀 수 있는 것 같아서 조금 성장한 느낌이 든다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;문제를 푼 로직은 다음과 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DFS를 재귀적으로 사용하여 각 난쟁이를 선택한 경우와 선택하지 않은 경우의 수를 모두 구한다. (19~25번째 줄)&lt;/li&gt;
&lt;li&gt;모든 경우 중 한 가지 경우의 난쟁이들을 선택한 뒤, 선택한 난쟁이의 수가 7이고 키의 합이 100인 경우 선택된 난쟁이들의 키를 출력한다. (9~17번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 풀면서 한 가지 배운 점이 있다면, 한 개의 리스트를 출력할 때, 리스트의 원소마다 구분자를 설정하여 한 줄로 출력할 수 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 15번째 줄에 다음과 같이 나타나 있다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;print(*sorted(answer), sep='\n')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less79_0&quot; data-id=&quot;79_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more79_1&quot; data-id=&quot;79_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content79_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less79_1&quot; data-id=&quot;79_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import sys

dwarf_list = [int(sys.stdin.readline()) for _ in range(9)]
dwarf_check = [0 for _ in range(9)]
answer = []


def dfs(n, count, sum_height):
	if n == 9:
		if count == 7 and sum_height == 100:
			for idx, v in enumerate(dwarf_check):
				if v:
					answer.append(dwarf_list[idx])
			
			print(*sorted(answer), sep='\n')
			sys.exit(0)
		return

	# select a dwarf
	dwarf_check[n] = 1
	dfs(n + 1, count + 1, sum_height + dwarf_list[n])
	
	# don't select a dwarf
	dwarf_check[n] = 0
	dfs(n + 1, count, sum_height)


dfs(0, 0, 0)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less79_1&quot; data-id=&quot;79_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>브루트포스</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/79</guid>
      <comments>https://empty-cloud.tistory.com/79#entry79comment</comments>
      <pubDate>Thu, 13 Feb 2020 18:37:52 +0900</pubDate>
    </item>
    <item>
      <title>[백준 6588번] 골드바흐의 추측</title>
      <link>https://empty-cloud.tistory.com/78</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/6588&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/do2qAl/btqBVMEEkp1/51wDdid5XxYQp9D79XzKP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/do2qAl/btqBVMEEkp1/51wDdid5XxYQp9D79XzKP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/do2qAl/btqBVMEEkp1/51wDdid5XxYQp9D79XzKP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdo2qAl%2FbtqBVMEEkp1%2F51wDdid5XxYQp9D79XzKP1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more78_0&quot; data-id=&quot;78_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content78_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less78_0&quot; data-id=&quot;78_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;수학&lt;/b&gt; 문제이고, &lt;b&gt;에라토스테네스의 체&lt;/b&gt;가 필요하다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제가 요구하는 것은 말 그대로 골드바흐의 추측을 검증하는 것이다.&lt;/p&gt;
&lt;p&gt;골드바흐의 추측이란 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;4보다 큰 모든 짝수는 두 홀수 소수의 합으로 나타낼 수 있다.&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;주어진 범위 내에 이 추측을 검증하기만 하면 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;에라토스테네스의 체로 주어진 범위 내의 모든 소수를 구한다. (5~18번째 줄)&lt;/li&gt;
&lt;li&gt;숫자 n을 입력받고 합이 n을 이루는 소수 a, b를 구한다. 두 소수 a, b를 찾았다면 &quot;n = a + b&quot;를 출력한다. (26~33번째 줄)&lt;/li&gt;
&lt;li&gt;두 소수 a, b를 찾지 못했다면 &quot;Goldbach's conjecture is wrong.&quot;을 출력한다. (35~36번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 문제가 생각보다 까다로운 점은 시간 초과에 있다.&lt;/p&gt;
&lt;p&gt;여러 가지 이유로 시간 초과가 날 수 있는데, 내가 제거한 시간 초과 요인들은 다음과 같다. (&lt;a href=&quot;https://www.acmicpc.net/board/view/44906&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 참고)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에라토스테네스의 체
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;에라토스테네스의 체는 주어진 수 n까지 선형 탐색을 통해 모든 수에 대해서 소수 판별을 한다. 따라서 숫자를 입력받을 때마다 에라토스테네스의 체를 사용할 필요가 없이 입력값의 경계인 1000000을 포함하는 범위, 즉 &lt;b&gt;1000001까지 한 번만 사용하면 된다. (18번째 줄)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소수 판정 범위
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;숫자 n의 소수 판정을 위해서 2부터 차례대로 n까지 나눗셈을 할 필요가 없다. n까지 나눗셈을 할 경우 O(n^2)의 시간 복잡도가 나오게 된다. &lt;b&gt;sqrt(n)까지만 나누어줘도 소수 판정을 할 수 있다&lt;/b&gt;&lt;b&gt; (9번째 줄)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소수의 조합
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;합이 n인 두 소수 a, b를 구하기 위해 에라토스테네스의 체로 구한 소수들의 모든 조합을 구할 필요가 없다. 모든 조합을 구할 경우 O(n^2)의 시간 복잡도가 나오게 된다. &lt;b&gt;n = a + b를 활용하여 선형 시간 안에 두 소수 a, b의 조합을 구할 수 있다. (28~30번째 줄)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less78_0&quot; data-id=&quot;78_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more78_1&quot; data-id=&quot;78_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content78_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less78_1&quot; data-id=&quot;78_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import sys
from math import sqrt


# implementation of Sieve of Eratosthenes
def eratosthenes(n):
	sieve = [True for _ in range(n)]
	
	for i in range(2, int(sqrt(n)) + 1):
		if sieve[i]:
			for j in range(i * i, n, i):
				sieve[j] = False
				
	return sieve


# run only once
prime_list = eratosthenes(1000001)

while True:
	n = int(sys.stdin.readline())
	if n == 0:
		break
	found = False
	
	# for linear search
	for a in range(2, 1000001):
		if prime_list[a]:
			b = n - a
			if prime_list[b]:
				found = True
				print(&quot;{0} = {1} + {2}&quot;.format(n, a, b))
				break
	
	if not found:
		print(&quot;Goldbach's conjecture is wrong.&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less78_1&quot; data-id=&quot;78_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>수학</category>
      <category>알고리즘</category>
      <category>에라토스테네스의 체</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/78</guid>
      <comments>https://empty-cloud.tistory.com/78#entry78comment</comments>
      <pubDate>Tue, 11 Feb 2020 16:06:28 +0900</pubDate>
    </item>
    <item>
      <title>[백준 1978번] 소수 찾기</title>
      <link>https://empty-cloud.tistory.com/77</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1978&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjO4nn/btqBVgyRmAM/rj9NQAqyWm7a7lUkiWlaMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjO4nn/btqBVgyRmAM/rj9NQAqyWm7a7lUkiWlaMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjO4nn/btqBVgyRmAM/rj9NQAqyWm7a7lUkiWlaMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjO4nn%2FbtqBVgyRmAM%2Frj9NQAqyWm7a7lUkiWlaMK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more77_0&quot; data-id=&quot;77_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content77_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less77_0&quot; data-id=&quot;77_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;수학&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;알고리즘 분류는 에라토스테네스의 체도 포함되어 있지만, 굳이 그럴 필요는 없는 것 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제에서 요구하는 바는 주어진 숫자들 중 소수가 몇 개인지 찾는 것이다.&lt;/p&gt;
&lt;p&gt;딱히 어려운 구현은 없기 때문에, 나는 소수를 판별하기 위해 다음의 조건을 생각하였다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;소수의 약수는 1과 n밖에 없다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;이 조건을 확인하는 함수는 8~16번째 줄에 작성되어 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;자연수를 입력받는다. (4~5번째 줄)&lt;/li&gt;
&lt;li&gt;주어진 수에 대해서 소수의 개수를 세고, 이를 출력한다. (19~23번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less77_0&quot; data-id=&quot;77_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more77_1&quot; data-id=&quot;77_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content77_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less77_1&quot; data-id=&quot;77_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import sys
from math import sqrt

n = int(sys.stdin.readline())
numbers = list(map(int, sys.stdin.readline().split()))


def is_prime(value):
	if value == 1:
		return False
	
	for i in range(2, int(sqrt(value) + 1)):
		if value % i == 0:
			return False
		
	return True


answer = 0
for i in numbers:
	if is_prime(i):
		answer += 1
print(answer)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less77_1&quot; data-id=&quot;77_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>수학</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/77</guid>
      <comments>https://empty-cloud.tistory.com/77#entry77comment</comments>
      <pubDate>Tue, 11 Feb 2020 02:40:11 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Java 8 변경사항</title>
      <link>https://empty-cloud.tistory.com/76</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java 8 변경사항&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;2014년에 발표된 &lt;b&gt;Java SE(Standard Edition) 8&lt;/b&gt; 버전에서는 다음과 같은 주요 변경사항이 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;람다 표현식 (Lambda expression):&lt;/b&gt; 함수형 프로그래밍이 가능하게 됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스트림 API (Stream API):&lt;/b&gt; 데이터를 추상화하여 다룰 수 있게 됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;java.time 패키지:&lt;/b&gt; 더 직관적이고 개선된 Date, Time API를 제공&lt;/li&gt;
&lt;li&gt;&lt;b&gt;나즈혼 (Nashorn):&lt;/b&gt; 자바스크립트의 새로운 엔진을 도입&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;각 변경사항들의 특징에 대해서 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;람다 표현식 (Lambda Expression)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;람다 표현식(Lambda Expression)이란?&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;람다 표현식&lt;/b&gt;&lt;/span&gt;이란 &lt;b&gt;익명 클래스의 한 개의 메소드를 식으로 표현한 것&lt;/b&gt;입니다. 여기서 &lt;span style=&quot;color: #006dd7;&quot;&gt;익명 클래스&lt;/span&gt;란 말 그대로 &lt;b&gt;이름이 없는 클래스로써, 단 한 개의 객체만을 생성할 수 있는 일회용 클래스&lt;/b&gt;입니다. (자바는 클래스의 선언과 동시에 객체를 생성하기 때문에 이름이 없으면 선언되는 그 순간에만 사용될 수 있습니다.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;익명 클래스의 예&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;new Object()
{
    int min(int x, int y)
    {
        return x &amp;lt; y ? x : y;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;람다 표현식의 예&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;(x, y) -&amp;gt; x &amp;lt; y ? x : y;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이러한 람다 표현식은 매개변수로 전달될 수도 있으며, 메소드의 결괏값으로 반환될 수도 있습니다. 따라서 &lt;span style=&quot;color: #ee2323;&quot;&gt;람다 표현식을 사용하면 기존의 불필요한 코드를 줄여주고, 작성된 코드의 가독성을 높여줍니다&lt;/span&gt;. Java SE 8부터는 이러한 람다 표현식을 사용하여 자바에서도 &lt;span style=&quot;color: #006dd7;&quot;&gt;함수형 프로그래밍&lt;/span&gt;을 할 수 있게 되었습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;람다 표현식 작성법&lt;/h3&gt;
&lt;p&gt;자바에서는 화살표(-&amp;gt;) 기호를 사용하여 람다 표현식을 작성할 수 있습니다. 문법은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;(매개변수 목록) -&amp;gt; {함수 몸체}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자바에서 람다 표현식을 사용할 때 주의할 점은 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;매개변수가 한 개인 경우 ()를 생략할 수 있습니다.&lt;/li&gt;
&lt;li&gt;함수 몸체가 한 개의 명령문으로만 이루어진 경우에는 {}를 생략할 수 있습니다.&lt;/li&gt;
&lt;li&gt;함수 몸체가 한 개의 return 문으로만 이루어진 경우에는 {}를 생략할 수 없습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;다음은 전통적인 스레드 생성 방식과 람다 표현식을 사용한 스레드 생성 방식을 비교하는 예제입니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;new Thread(new Runnable()
{
	public void run()
    {
    	System.out.println(&quot;전통적인 방식의 스레드 생성&quot;);
    }
}).start();


new Thread(()-&amp;gt;{
	System.out.println(&quot;람다 표현식을 사용한 스레드 생성&quot;);
}).start();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 예제에서 볼 수 있듯이, 매개변수로 정의된 Runnable() 인터페이스와 run() 추상 메소드를 람다 표현식을 사용하여 더 간결하게 구현한 것을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수형 인터페이스 (Functional Interface)&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수형 인터페이스&lt;/span&gt;란 람다 표현식을 하나의 변수에 대입할 때 사용하는 참조 변수의 타입을 의미합니다. &lt;b&gt;함수형 인터페이스는 추상 클래스와 달리 단 한 개의 추상 메소드만을 가져야 합니다&lt;/b&gt;. 또, 다음과 같은 어노테이션(annotation)을 사용하여 함수형 인터페이스임을 명시할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@FunctionalInterface&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같은 어노테이션을 인터페이스의 선언 위에 붙이면, 컴파일러는 해당 인터페이스를 함수형 인터페이스로 인식합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음은 함수형 인터페이스의 예제입니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 함수형 인터페이스 구현
@FunctionalInterface
interface ExampleInterface
{
	public int doSomething(int x, int y);
}

public class test
{
	public static void main(String[] args)
	{
		ExampleInterface implemented = (x, y) -&amp;gt; x + y;		// 추상 메소드 구현
		System.out.println(implemented.doSomething(10, 11));	// 21을 출력함
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 예제에서 볼 수 있듯이, &lt;i&gt;implemented&lt;/i&gt; 변수는 람다 표현식으로 구현된 객체를 가리키고 있습니다. &lt;i&gt;implemented&lt;/i&gt; 변수는 구현된 함수형 인터페이스 내의 &lt;i&gt;doSomething()&lt;/i&gt; 메소드를 실행할 때마다, 람다 표현식으로 구현한 추상 메소드를 실행합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스트림 API (Stream API)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스트림 API(Stream API)란?&lt;/h3&gt;
&lt;p&gt;자바에서는 여러 개의 데이터를 저장하기 위해서 배열이나 컬렉션을 사용합니다. 그리고 이렇게 저장된 데이터에 접근하기 위해서는 반복문이나 반복자(iterator)를 사용하여 매번 코드를 작성해야 했습니다.&lt;/p&gt;
&lt;p&gt;하지만 이렇게 작성된 코드는 길이가 길고 가독성도 떨어지며, 코드의 재사용이 거의 불가능합니다. 또한, 정형화된 처리 패턴을 가지지 못했기 때문에 데이터마다 다른 방법으로 접근해야만 했습니다.&lt;/p&gt;
&lt;p&gt;이러한 문제점을 극복하기 위해서 도입된 방법이 스트림 API입니다. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;스트림 API&lt;/b&gt;&lt;/span&gt;는 &lt;b&gt;데이터를 추상화해서 다루므로, 다양한 형태로 저장된 데이터를 위한 공통된 방법을 제공&lt;/b&gt;합니다. 따라서 스트림 API를 사용하면 배열이나 컬렉션 뿐만아니라 파일에 저장된 데이터도 모두 같은 방법으로 다룰 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스트림 API의 특징&lt;/h3&gt;
&lt;p&gt;스트림 API는 다음과 같은 특징을 가집니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스트림은 외부 반복을 통해 작업하는 컬렉션과는 다르게 내부 반복을 통해 작업을 수행합니다.&lt;/li&gt;
&lt;li&gt;스트림은 단 한번만 사용할 수 있습니다. (= 재사용이 불가능합니다.)&lt;/li&gt;
&lt;li&gt;스트림은 원본 데이터를 변경하지 않습니다.&lt;/li&gt;
&lt;li&gt;스트림의 연산은 필터-맵(filter-map) 기반의 API를 사용하여 lazy 연산을 통해 성능을 최적화합니다.&lt;/li&gt;
&lt;li&gt;스트림은 parallelStream() 메소드를 통해 간단한 병렬처리를 지원합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;다음은 스트림 API의 예제입니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 정수형 배열에서 스트림 생성
Integer[] arr1 = new Integer[] {1, 5, 11, 13, 20, 52};
Stream stream1 = Arrays.stream(arr1);
stream1.map(i -&amp;gt; i * 2);
stream1.filter(i -&amp;gt; i % 2 == 0);			// 재사용이 불가능하기 때문에 에러 발생!


// 정수형 배열에서 스트림 생성
Integer[] arr2 = new Integer[] {1, 5, 11, 13, 20, 52};
Stream stream2;
stream2 = Arrays.stream(arr2)
                .filter(i -&amp;gt; i % 2 != 0)	// {1, 5, 11, 13}
                .map(i -&amp;gt; i * 2);			// {2, 10, 22, 26}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;스트림 API는 다음과 같이 세 가지 단계에 걸쳐서 동작합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스트림 생성&lt;/li&gt;
&lt;li&gt;스트림 중개 연산 (filter)&lt;/li&gt;
&lt;li&gt;스트림 최종 연산 (map)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위의 예제에서 필터-맵이 동작하는 순서는 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pVRbr/btqBO7QJiQV/u8V5nCGlAAsO9BmPvHwEnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pVRbr/btqBO7QJiQV/u8V5nCGlAAsO9BmPvHwEnK/img.png&quot; data-alt=&quot;스트림 API의 흐름&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pVRbr/btqBO7QJiQV/u8V5nCGlAAsO9BmPvHwEnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpVRbr%2FbtqBO7QJiQV%2Fu8V5nCGlAAsO9BmPvHwEnK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스트림 API의 흐름&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;java.time 패키지&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;JDK 1.0에서는 Date 클래스를 사용하여 날짜에 관한 연산을 수행했습니다. 하지만 현재는 Date 클래스의 대부분의 메소드는 사용을 권장하지 않습니다. (deprecated) JDK 1.1부터 제공된 Calendar 클래스는 날짜와 시간에 대한 정보를 쉽게 얻을 수 있었습니다. 하지만 Calendar 클래스는 다음과 같은 문제점을 가지고 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Calendar 인스턴스는 immutable object가 아니라서 값이 수정될 수 있습니다.&lt;/li&gt;
&lt;li&gt;윤초(leap second)와 같은 특별한 상황을 고려하지 않습니다.&lt;/li&gt;
&lt;li&gt;Calendar 클래스에서는 월(month)을 나타낼 때 1~12가 아닌 0~11로 표현해야합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;따라서 많은 개발자들은 Calendar 클래스뿐만 아니라 더 나은 성능의 Joda-Time이라는 라이브러리를 함께 사용해왔습니다. Java SE 8 버전에서는 이러한 Joda-Time 라이브러리를 발전시킨 새로운 날짜/시간 API인 java.time 패키지를 제공합니다. java.time 패키지는 위와 같은 문제점을 모두 해결했으며, 다양한 기능을 지원하는 하위 패키지를 포함하고 있습니다.&lt;/p&gt;
&lt;p&gt;다음은 java.date 패키지의 예입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1581318037521&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LocalDate today = LocalDate.now();
System.out.println(&quot;올해는&quot; + today.getYear() + &quot;년입니다.&quot;);

LocalDate otherDay = today.withYear(1982);
System.out.println(&quot;올해는&quot; + otherDay.getYear() + &quot;년입니다.&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;나즈혼 (Nashorn)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;지금까지 자바스크립트의 기본 엔진으로는 &lt;b&gt;모질라의 라이노 (Rhino)&lt;/b&gt;가 사용되어 왔습니다. 하지만 세월이 흐르면서 자바의 최신 개선 사항 등을 제대로 활용하지 못하는 등 노후화 된 모습을 보여주게 됩니다.&lt;/p&gt;
&lt;p&gt;따라서 Java SE 8 버전부터는 자바스크립트의 새로운 엔진으로 &lt;b&gt;오라클의 나즈혼 (Nashorn)&lt;/b&gt;을 도입하게 됩니다. 나즈혼은 기존에 사용되어 온 라이노에 비해 성능과 메모리 관리 측면에서 크게 개선된 스크립트 엔진입니다.&lt;/p&gt;</description>
      <category>프로그래밍 언어/Java</category>
      <category>Java</category>
      <category>Java 8</category>
      <category>java.time</category>
      <category>lambda</category>
      <category>Nashorn</category>
      <category>Stream API</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/76</guid>
      <comments>https://empty-cloud.tistory.com/76#entry76comment</comments>
      <pubDate>Sun, 9 Feb 2020 03:45:51 +0900</pubDate>
    </item>
    <item>
      <title>[백준 9613번] GCD 합</title>
      <link>https://empty-cloud.tistory.com/75</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/9613&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwNs3V/btqBJ8JDQHr/9rHxK5lUXMdIork5FWkF4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwNs3V/btqBJ8JDQHr/9rHxK5lUXMdIork5FWkF4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwNs3V/btqBJ8JDQHr/9rHxK5lUXMdIork5FWkF4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwNs3V%2FbtqBJ8JDQHr%2F9rHxK5lUXMdIork5FWkF4K%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more75_0&quot; data-id=&quot;75_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content75_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less75_0&quot; data-id=&quot;75_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;수학&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;최대 공약수를 활용한 문제인데, 최대 공약수를 구하는 부분은 math 모듈의 gcd 메소드를 사용하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;숫자의 개수와 숫자들을 입력받는다. (6~7번째 줄)&lt;/li&gt;
&lt;li&gt;주어진 숫자의 모든 경우의 수에 대해서 최대 공약수를 구하고, 이 최대공약수들의 합을 구해야 하기 때문에 answer 변수에 더해준다. (9~13번째 줄)&lt;/li&gt;
&lt;li&gt;주어진 테스트 케이스만큼 실행한다. (4~5번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less75_0&quot; data-id=&quot;75_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more75_1&quot; data-id=&quot;75_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content75_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less75_1&quot; data-id=&quot;75_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import sys
from math import gcd

t = int(sys.stdin.readline())
for _ in range(t):
	line = list(map(int, sys.stdin.readline().split()))
	n, numbers = line[0], line[1:]
	
	answer = 0
	for i in range(n - 1):
		for j in range(i + 1, n):
			answer += gcd(numbers[i], numbers[j])
	print(answer)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less75_1&quot; data-id=&quot;75_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>gcd</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/75</guid>
      <comments>https://empty-cloud.tistory.com/75#entry75comment</comments>
      <pubDate>Thu, 6 Feb 2020 16:21:20 +0900</pubDate>
    </item>
    <item>
      <title>[백준 5373번] 큐빙</title>
      <link>https://empty-cloud.tistory.com/74</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/5373&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blq7Ht/btqBD0ZiWob/UGZVZcCDSRDeVYSKgH6mA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blq7Ht/btqBD0ZiWob/UGZVZcCDSRDeVYSKgH6mA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blq7Ht/btqBD0ZiWob/UGZVZcCDSRDeVYSKgH6mA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblq7Ht%2FbtqBD0ZiWob%2FUGZVZcCDSRDeVYSKgH6mA0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more74_0&quot; data-id=&quot;74_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content74_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less74_0&quot; data-id=&quot;74_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;시뮬레이션&lt;/b&gt; 문제이다. (시뮬레이션 구현을 위해 노가다가 필요하다..)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제에서 요구하는 바는 주어진 순서대로 큐브를 회전시켰을 때의 상태를 구하는 것이다.&lt;/p&gt;
&lt;p&gt;문제를 푸는 로직 자체는 매우 쉽지만, 이를 구현하기 위한 방법이 매우 까다롭다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;먼저, 나는 문제를 풀기 위해 다음과 같이 큐브의 전개도를 구성하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4362E/btqBHTcDLAS/wqO2HJ5kANfoSXp37ydhXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4362E/btqBHTcDLAS/wqO2HJ5kANfoSXp37ydhXk/img.png&quot; data-alt=&quot;큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4362E/btqBHTcDLAS/wqO2HJ5kANfoSXp37ydhXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4362E%2FbtqBHTcDLAS%2FwqO2HJ5kANfoSXp37ydhXk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이 전개도는 &lt;span style=&quot;color: #333333;&quot;&gt;가상의 위치로써,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;큐브가 회전하더라도 어떻게 큐브가 회전하였는지 우리가 알기 쉽게 도와준다.&lt;/p&gt;
&lt;p&gt;이 전개도를 구현하기 위해 나는 cube라는 3차원 리스트 변수를 두었고, 다음과 같이 구성하였다.&lt;/p&gt;
&lt;p&gt;즉, cube는 3*3 2차원 배열을 6개 가진 변수이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VfTBU/btqBHTqaSHP/nMFdt8ELNOsiBledj2f8C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VfTBU/btqBHTqaSHP/nMFdt8ELNOsiBledj2f8C1/img.png&quot; data-alt=&quot;cube변수의 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VfTBU/btqBHTqaSHP/nMFdt8ELNOsiBledj2f8C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVfTBU%2FbtqBHTqaSHP%2FnMFdt8ELNOsiBledj2f8C1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;cube변수의 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;큐브의 각 칸에 대한 숫자들은 나중에 큐브가 회전할 때 우리가 쉽게 이해하기 위해 임의로 둔 숫자이다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;이제 우리는 &lt;span style=&quot;color: #333333;&quot;&gt;코드로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;큐브를 구현하였으니, 모든 회전 명령에 대해서 구현하여야 한다.&lt;/p&gt;
&lt;p&gt;다음은 큐브가 회전했을 때의 전개도 상태를 나타낸 그림들이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uSQKA/btqBGfVerhp/a1oKiQJNCYmtjjAsRw6wFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uSQKA/btqBGfVerhp/a1oKiQJNCYmtjjAsRw6wFK/img.png&quot; data-alt=&quot;윗 면을 회전한 큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uSQKA/btqBGfVerhp/a1oKiQJNCYmtjjAsRw6wFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuSQKA%2FbtqBGfVerhp%2Fa1oKiQJNCYmtjjAsRw6wFK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윗 면을 회전한 큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byoL1d/btqBGZ5s0hR/O5drXV9IPTlYPSKT962KXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byoL1d/btqBGZ5s0hR/O5drXV9IPTlYPSKT962KXK/img.png&quot; data-alt=&quot;아랫 면을 회전한 큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byoL1d/btqBGZ5s0hR/O5drXV9IPTlYPSKT962KXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyoL1d%2FbtqBGZ5s0hR%2FO5drXV9IPTlYPSKT962KXK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아랫 면을 회전한 큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bufqSr/btqBD2bKgmn/dKFpwhlDvwaFikp2rOW91K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bufqSr/btqBD2bKgmn/dKFpwhlDvwaFikp2rOW91K/img.png&quot; data-alt=&quot;앞 면을 회전한 큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bufqSr/btqBD2bKgmn/dKFpwhlDvwaFikp2rOW91K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbufqSr%2FbtqBD2bKgmn%2FdKFpwhlDvwaFikp2rOW91K%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;앞 면을 회전한 큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SkfPe/btqBFuL7ymM/RrzFaK93f0HKy1nEDxEukk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SkfPe/btqBFuL7ymM/RrzFaK93f0HKy1nEDxEukk/img.png&quot; data-alt=&quot;뒷 면을 회전한 큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SkfPe/btqBFuL7ymM/RrzFaK93f0HKy1nEDxEukk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSkfPe%2FbtqBFuL7ymM%2FRrzFaK93f0HKy1nEDxEukk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;뒷 면을 회전한 큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkrYZj/btqBGYyITgY/uUC2AEKQy6jNpCzWHwUjLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkrYZj/btqBGYyITgY/uUC2AEKQy6jNpCzWHwUjLK/img.png&quot; data-alt=&quot;왼쪽 면을 회전한 큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkrYZj/btqBGYyITgY/uUC2AEKQy6jNpCzWHwUjLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkrYZj%2FbtqBGYyITgY%2FuUC2AEKQy6jNpCzWHwUjLK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;왼쪽 면을 회전한 큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J9med/btqBHUCCkK3/hkeizbKjoApVjkG2X32YsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J9med/btqBHUCCkK3/hkeizbKjoApVjkG2X32YsK/img.png&quot; data-alt=&quot;오른쪽 면을 회전한 큐브의 전개도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J9med/btqBHUCCkK3/hkeizbKjoApVjkG2X32YsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ9med%2FbtqBHUCCkK3%2FhkeizbKjoApVjkG2X32YsK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오른쪽 면을 회전한 큐브의 전개도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;각 회전 명령에 대한 코드는 4~86번째 줄에 구현되어 있다.&lt;/p&gt;
&lt;p&gt;이제 필요한 함수는 모두 작성하였으니, 문제를 풀면 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;큐브를 초기화한다. (92~99번째 줄)&lt;/li&gt;
&lt;li&gt;주어진 모든 명령에 대해서 큐브를 회전시키고 출력한다. (101~109번째 줄)&lt;/li&gt;
&lt;li&gt;모든 테스트 케이스에 대해서 수행한다. (89~91번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less74_0&quot; data-id=&quot;74_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more74_1&quot; data-id=&quot;74_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content74_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less74_1&quot; data-id=&quot;74_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import sys


def get_plain_index(p):
	if p == 'U':
		return 0
	elif p == 'L':
		return 1
	elif p == 'F':
		return 2
	elif p == 'R':
		return 3
	elif p == 'B':
		return 4
	elif p == 'D':
		return 5


def rotate(p, d):
	global cube
	idx = get_plain_index(p)
	
	if d == '-':
		# rotate plain
		cube[idx] = list(reversed(list(map(list, zip(*cube[idx])))))
		
		if p == 'U':
			cube[1][0], cube[2][0], cube[3][0], cube[4][0] = cube[4][0], cube[1][0], cube[2][0], cube[3][0]
		elif p == 'D':
			cube[1][2], cube[2][2], cube[3][2], cube[4][2] = cube[2][2], cube[3][2], cube[4][2], cube[1][2]
		elif p == 'F':
			temp = cube[0][2]
			cube[0][2] = list(map(list, zip(*cube[3])))[0]
			cube[3][0][0], cube[3][1][0], cube[3][2][0] = list(reversed(cube[5][0]))
			cube[5][0] = list(map(list, zip(*cube[1])))[2]
			cube[1][0][2], cube[1][1][2], cube[1][2][2] = list(reversed(temp))
		elif p == 'B':
			temp = cube[0][0]
			cube[0][0] = list(reversed(list(zip(*cube[1]))[0]))
			cube[1][0][0], cube[1][1][0], cube[1][2][0] = cube[5][2]
			cube[5][2] = list(reversed(list(zip(*cube[3]))[2]))
			cube[3][0][2], cube[3][1][2], cube[3][2][2] = temp
		elif p == 'L':
			temp = list(zip(*cube[0]))[0]
			cube[0][0][0], cube[0][1][0], cube[0][2][0] = list(map(list, zip(*cube[2])))[0]
			cube[2][0][0], cube[2][1][0], cube[2][2][0] = list(map(list, zip(*cube[5])))[0]
			cube[5][0][0], cube[5][1][0], cube[5][2][0] = list(reversed(list(zip(*cube[4]))[2]))
			cube[4][0][2], cube[4][1][2], cube[4][2][2] = list(reversed(temp))
		elif p == 'R':
			temp = list(map(list, zip(*cube[0])))[2]
			cube[0][0][2], cube[0][1][2], cube[0][2][2] = list(reversed(list(zip(*cube[4]))[0]))
			cube[4][0][0], cube[4][1][0], cube[4][2][0] = list(reversed(list(zip(*cube[5]))[2]))
			cube[5][0][2], cube[5][1][2], cube[5][2][2] = list(map(list, zip(*cube[2])))[2]
			cube[2][0][2], cube[2][1][2], cube[2][2][2] = temp
	elif d == '+':
		# rotate plain
		cube[idx] = list(map(list, zip(*reversed(cube[idx]))))
		
		if p == 'U':
			cube[1][0], cube[2][0], cube[3][0], cube[4][0] = cube[2][0], cube[3][0], cube[4][0], cube[1][0]
		elif p == 'D':
			cube[1][2], cube[2][2], cube[3][2], cube[4][2] = cube[4][2], cube[1][2], cube[2][2], cube[3][2]
		elif p == 'F':
			temp = cube[0][2]
			cube[0][2] = list(reversed(list(zip(*cube[1]))[2]))
			cube[1][0][2], cube[1][1][2], cube[1][2][2] = cube[5][0]
			cube[5][0] = list(reversed(list(zip(*cube[3]))[0]))
			cube[3][0][0], cube[3][1][0], cube[3][2][0] = temp
		elif p == 'B':
			temp = cube[0][0]
			cube[0][0] = list(map(list, zip(*cube[3])))[2]
			cube[3][0][2], cube[3][1][2], cube[3][2][2] = list(reversed(cube[5][2]))
			cube[5][2] = list(map(list, zip(*cube[1])))[0]
			cube[1][0][0], cube[1][1][0], cube[1][2][0] = list(reversed(temp))
		elif p == 'L':
			temp = list(map(list, zip(*cube[0])))[0]
			cube[0][0][0], cube[0][1][0], cube[0][2][0] = list(reversed(list(zip(*cube[4]))[2]))
			cube[4][0][2], cube[4][1][2], cube[4][2][2] = list(reversed(list(zip(*cube[5]))[0]))
			cube[5][0][0], cube[5][1][0], cube[5][2][0] = list(map(list, zip(*cube[2])))[0]
			cube[2][0][0], cube[2][1][0], cube[2][2][0] = temp
		elif p == 'R':
			temp = list(zip(*cube[0]))[2]
			cube[0][0][2], cube[0][1][2], cube[0][2][2] = list(map(list, zip(*cube[2])))[2]
			cube[2][0][2], cube[2][1][2], cube[2][2][2] = list(map(list, zip(*cube[5])))[2]
			cube[5][0][2], cube[5][1][2], cube[5][2][2] = list(reversed(list(zip(*cube[4]))[0]))
			cube[4][0][0], cube[4][1][0], cube[4][2][0] = list(reversed(temp))


# for all test cases
t = int(sys.stdin.readline())
for _ in range(t):
	cube = [
		[['w' for c in range(3)] for r in range(3)],
		[['g' for c in range(3)] for r in range(3)],
		[['r' for c in range(3)] for r in range(3)],
		[['b' for c in range(3)] for r in range(3)],
		[['o' for c in range(3)] for r in range(3)],
		[['y' for c in range(3)] for r in range(3)],
	]

	# for all operations
	n = int(sys.stdin.readline().strip())
	command_list = sys.stdin.readline().strip().split()
	for command in command_list:
		plain, direction = map(str, [c for c in command])
		rotate(plain, direction)

	for r in cube[0]:
		print(''.join(r))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less74_1&quot; data-id=&quot;74_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>시뮬레이션</category>
      <category>알고리즘</category>
      <category>큐브</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/74</guid>
      <comments>https://empty-cloud.tistory.com/74#entry74comment</comments>
      <pubDate>Mon, 3 Feb 2020 02:23:57 +0900</pubDate>
    </item>
    <item>
      <title>[운영체제] 가상 메모리 관리</title>
      <link>https://empty-cloud.tistory.com/73</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Virtual Memory Management (가상 메모리 관리)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가상 메모리&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;란 메모리 내에 완전히 존재하지 않는 프로세스를 실행하는 기술을 의미한다&lt;/span&gt;. 프로그램의 인스트럭션들은 실행되기 위해서 메모리에 로드되어야 하지만, 프로그램 전체가 필요한 것은 아니다. 만약 그렇다 하더라도, 동시에 프로그램 전체를 사용하지는 않는다. 즉, &lt;span style=&quot;color: #ee2323;&quot;&gt;프로그램이 CPU에 의해 실제로 사용되는 부분만 메모리로 로드하고, 사용되지 않는 부분은 디스크로 옮겨서 실제 메모리를 대체하도록 하는 것이다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;프로그램의 일부만 메모리로 로드하여 실행하는 것은 다음과 같은 장점이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;물리 메모리의 크기에 제한받지 않는다.&lt;/li&gt;
&lt;li&gt;더 많은 프로그램이 동시에 실행될 수 있다. (CPU utilization 증가)&lt;/li&gt;
&lt;li&gt;페이지 테이블 전체를 읽을 필요가 없기 때문에 프로그램을 Load/Swap 하기 위한 I/O 연산이 줄어든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Demand Paging (요구 페이징)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;요구 페이징&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;이란 프로세스를 구성하는 페이지 전체를 메모리로 적재하는 것이 아니라, 당장 필요한 페이지만 메모리에 적재하는 기술이다&lt;/span&gt;. &lt;span style=&quot;color: #333333;&quot;&gt;프로세스 내에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;한 번도 접근되지 않은 페이지는 절대로 메모리에 로드되지 않는다.&lt;/p&gt;
&lt;p&gt;요구 페이징의 기본적인 개념으로 디스크의 페이지를 메모리로 적재할 때, Pager는 어떤 페이지가 사용될지 예측하고 메모리로 적재시킨다. 이때, 이미 메모리에 적재되어있는 페이지와 디스크에 있는 페이지를 구분해야 한다. 이를 위해서 valid-invalid bit를 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;718&quot; height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnF7nL/btqBFNYy4UI/shkztDOj3To2AHGwzkkcY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnF7nL/btqBFNYy4UI/shkztDOj3To2AHGwzkkcY1/img.png&quot; data-alt=&quot;프로세스가 3개의 페이지만을 사용할 때의 상황&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnF7nL/btqBFNYy4UI/shkztDOj3To2AHGwzkkcY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnF7nL%2FbtqBFNYy4UI%2FshkztDOj3To2AHGwzkkcY1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;718&quot; height=&quot;538&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로세스가 3개의 페이지만을 사용할 때의 상황&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위의 그림에서 프로세스는 A~H를 다 쓴다고 생각하지만, 실제로 메모리에는 A, C, F만 로드되어 있다. 이때 페이지 테이블에 존재하지 않는 페이지에 프로세스가 접근하게 된다면 디스크에서 해당하는 페이지를 메모리로 로드하고, 페이지 테이블을 업데이트한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Page Fault (페이지 부재)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;페이지 부재&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;는 프로세스가 메모리에 존재하지 않는 페이지에 접근하려고 할 때 발생한다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/psglb/btqBDXH69Dq/ZRlVGDLty3QyjnBvuLogs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/psglb/btqBDXH69Dq/ZRlVGDLty3QyjnBvuLogs1/img.png&quot; data-alt=&quot;Page Fault의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/psglb/btqBDXH69Dq/ZRlVGDLty3QyjnBvuLogs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpsglb%2FbtqBDXH69Dq%2FZRlVGDLty3QyjnBvuLogs1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Page Fault의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Copy-on-Write (COW)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;fork() system call을 사용하면 자식 프로세스는 부모 프로세스를 복제한다. 즉, 프로세스를 복제하므로 부모와 자식 프로세스에 해당하는 메모리 내의 페이지 또한 중복된다. 게다가 fork() system call을 사용하면 대부분 exec() system call을 호출하기 때문에, 자식 프로세스는 제거되고 중복된 페이지 또한 메모리에서 해제되는데, 이는 운영체제 관점에서 매우 낭비적인 행위이다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;COW(Copy-on-Write)&lt;/b&gt;&lt;/span&gt;는 이러한 페이지의 불필요한 중복을 줄이는 방법이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;fork()를 통해 부모 프로세스가 소유하고 있던 메모리 영역은 모두 '&lt;span style=&quot;color: #006dd7;&quot;&gt;copy-on-write&lt;/span&gt;'로 표시가 된다. 만약 자식 프로세스가 공유된 부모 프로세스의 페이지들 중 어떤 페이지라도 수정을 한다면 그때 페이지를 복사하여 수정한 후, 수정된 페이지를 메모리에 따로 저장한다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Mt2c/btqBDbs2gth/nqrakXv9TfLxSYbZtrNvH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Mt2c/btqBDbs2gth/nqrakXv9TfLxSYbZtrNvH0/img.png&quot; data-alt=&quot;COW(Copy-on-Write)의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Mt2c/btqBDbs2gth/nqrakXv9TfLxSYbZtrNvH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Mt2c%2FbtqBDbs2gth%2FnqrakXv9TfLxSYbZtrNvH0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;COW(Copy-on-Write)의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;COW의 장점은 자식 프로세스가 메모리에 로드된 페이지를 수정할 때에만 복사하기 때문에 기존의 fork()를 사용하여 페이지 전체를 복사할 때보다 빠르다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Page Replacement (페이지 교체)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;멀티 프로그래밍의 degree를 증가시키기 위해 프로세스를 계속 실행하다보면 Page over-allocation이 발생한다. 예를 들어 메모리에 프레임이 20개 있고, 한 개의 프로세스당 5개의 페이지가 필요하다면 총 4개의 프로세스가 동작할 수 있다. 하지만 어떤 프로세스가 추가적인 페이지가 필요하게 되면 Page Fault가 발생하고, 이를 해결하기 위해 디스크로부터 적절한 페이지를 찾아서 메모리로 적재시키려고 한다. 하지만 이 때 메모리에 남는 공간이 없으므로 이에 대한 해결책이 필요하다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본적인 Page Replacement (페이지 교체)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;600&quot; height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MfLTH/btqBD2boeqz/tjanhmLHkuOw6EzwQ6Si30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MfLTH/btqBD2boeqz/tjanhmLHkuOw6EzwQ6Si30/img.png&quot; data-alt=&quot;기본적인 페이지 교체의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MfLTH/btqBD2boeqz/tjanhmLHkuOw6EzwQ6Si30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMfLTH%2FbtqBD2boeqz%2FtjanhmLHkuOw6EzwQ6Si30%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;600&quot; height=&quot;351&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기본적인 페이지 교체의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;기본적인 페이지 교체 방식은 메모리 내에서 교체될 victim 페이지를 선택하여 swap-out하고, 사용할 페이지를 디스크로부터 swap-in 한다. 이 때 페이지 테이블 내의 valid-invalid 비트를 사용한다. 하지만 이는 swap-in &amp;amp; swap-out을 위해 디스크에 2번 접근해야하기 때문에 매우 느리다. 따라서 우리는 &lt;span style=&quot;color: #006dd7;&quot;&gt;modify-bit&lt;/span&gt;를 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Modify-bit&lt;/span&gt;는 하드웨어적으로 구현하며, 해당 페이지가 최근에 변경된 적이 있으면 1로 설정하고, 변경된 적이 없으면 0으로 설정한다. &lt;span style=&quot;color: #ee2323;&quot;&gt;Swap-out을 수행하면서 만약 해당 페이지의 modify-bit가 0이라면(= 최근에 사용된 적이 없다면) 그대로 버리고, 1이라면 disk에 저장한다&lt;/span&gt;. 이와 같이 Modify-bit를 사용한 방법은 I/O 연산을 절반정도 줄일 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Page Replacement는 적을수록 좋다. 왜냐하면 디스크와 관련된 I/O 연산이 줄어들기 때문에 응답시간이 더 짧아지기 때문이다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;FIFO Page Replacement&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;FIFO 페이지 교체&lt;/span&gt;&lt;/b&gt;는 가장 간단한 페이지 교체 알고리즘이며, &lt;span style=&quot;color: #ee2323;&quot;&gt;메모리 내에서 가장 오래된 페이지를 victim으로 선택하여 교체하는 방법&lt;/span&gt;이다. &lt;b&gt;항상 최적의 결과를 가져다주진 않지만, 동작은 올바르게 한다는 것이 보장된다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enjrgB/btqBGe9xGb8/yty71dMcCcl8evLHfJDVyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enjrgB/btqBGe9xGb8/yty71dMcCcl8evLHfJDVyk/img.png&quot; data-alt=&quot;FIFO Page Replacement의 예. 파란색 원은 교체된 페이지를 나타내며, 총 15번의 페이지 교체가 발생한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enjrgB/btqBGe9xGb8/yty71dMcCcl8evLHfJDVyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenjrgB%2FbtqBGe9xGb8%2Fyty71dMcCcl8evLHfJDVyk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;FIFO Page Replacement의 예. 파란색 원은 교체된 페이지를 나타내며, 총 15번의 페이지 교체가 발생한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;메모리 내의 프레임의 갯수가 증가할 수록 Page Fault가 줄어드는 것이 이상적이지만, &lt;span style=&quot;color: #ee2323;&quot;&gt;FIFO 페이지 교체에서는 프레임의 갯수가 늘어남에도 불구하고 Page Fault가 증가하는 경우가 존재&lt;/span&gt;한다. 이를 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Belady's anomaly&lt;/b&gt;&lt;/span&gt;라고 한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Optimal Page Replacement&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Optimal 페이지 교체&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;는 가장 오랫동안 사용되지 않을 페이지를 교체하는 방법이다&lt;/span&gt;. Page Fault가 가장 적다는 것이 보장되며 Belady's anomaly도 일어나지 않는다. 하지만 미래의 페이지에 대한 정보가 필요하기 때문에 실제로 구현하기는 어렵다. (프로세스 스케줄링의 SJF와 비슷하다)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sX1XM/btqBFNdgGUS/Xy71aWibkyrvPX0AK32r91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sX1XM/btqBFNdgGUS/Xy71aWibkyrvPX0AK32r91/img.png&quot; data-alt=&quot;Optimal Page Replacement의 예. 총 9번의 페이지 교체가 발생한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sX1XM/btqBFNdgGUS/Xy71aWibkyrvPX0AK32r91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsX1XM%2FbtqBFNdgGUS%2FXy71aWibkyrvPX0AK32r91%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Optimal Page Replacement의 예. 총 9번의 페이지 교체가 발생한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LRU Page Replacement (LRU: Least Recently Used)&lt;/h3&gt;
&lt;p&gt;Optimal 페이지 교체가 실제로 구현하기 어렵기 때문에 우리는 &lt;b&gt;Optimal 페이지 교체 알고리즘의 Approximation을 사용한다&lt;/b&gt;. 과거의 정보를 사용하여 미래의 대한 정보를 추정한다. 즉, &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;LRU 페이지 교체&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;는 최근에 사용한 페이지 중에서 가장 오래된 페이지를 victim으로 선택하는 방법이다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1dFI1/btqBEBSaruB/xfAfpU29SlKvSkPrHCXK1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1dFI1/btqBEBSaruB/xfAfpU29SlKvSkPrHCXK1k/img.png&quot; data-alt=&quot;LRU Page Replacement의 예. 12번의 페이지 교체가 발생한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1dFI1/btqBEBSaruB/xfAfpU29SlKvSkPrHCXK1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1dFI1%2FbtqBEBSaruB%2FxfAfpU29SlKvSkPrHCXK1k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LRU Page Replacement의 예. 12번의 페이지 교체가 발생한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;LRU 페이지 교체를 구현하기 위해 하드웨어를 사용한 다음의 두 가지 방법이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Counter&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;CPU에 클럭 레지스터를 추가한다. 이 레지스터는 메모리에 엑세스 할 때마다 증가한다.&lt;/li&gt;
&lt;li&gt;페이지를 참조할 때마다 클럭 레지스터의 값이 페이지 테이블의 'time-of-use' 필드에 저장된다. 이렇게 함으로써 우리는 레지스터의 값을 통해 가장 최근에 페이지를 참조한 시간을 알 수 있다.&lt;/li&gt;
&lt;li&gt;페이지 교체 시, 참조된 횟수가 가장 적은(time-of-use 값이 가장 작은) 페이지를 선택하여 교체한다.&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;페이지 테이블 내의 모든 값을 비교해야 하기 때문에 full search에 대한 오버헤드가 발생한다.&lt;/li&gt;
&lt;li&gt;페이지 테이블을 수정할 때 클럭 레지스터의 값이 유지되어야 한다.&lt;/li&gt;
&lt;li&gt;클럭 레지스터에 대한 overflow를 고려해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stack&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;페이지들을 관리할 스택을 사용하며, 이는 doubly-linked 리스트로 구현되어 있다.&lt;/li&gt;
&lt;li&gt;스택의 바닥에 있는 페이지가 무조건 victim이다.&lt;/li&gt;
&lt;li&gt;페이지가 참조될 때마다 스택에서 제거되고 다시 스택의 top으로 push된다. 따라서 가장 최근에 사용된 페이지는 스택의 top에 위치하게 된다.&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;페이지를 참조할 때마다 스택 내 페이지들의 위치 이동에 대한 오버헤드가 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Counting-based Page Replacement&lt;/h3&gt;
&lt;p&gt;Counting-based 페이지 교체는 페이지를 사용할 때마다 횟수를 기록하는 방법이다. 이 방법에는 다음과 같이 두 가지가 존재한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LFU (Least Frequently Used)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;카운트 값이 가장 작은 페이지를 victim으로 지정하고 교체하는 방법이다.&lt;/li&gt;
&lt;li&gt;문제점
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;앞으로 많이 사용할 페이지가 들어오더라도, 적은 횟수를 가지고 있기때문에 victim이 될 수 있다.&lt;/li&gt;
&lt;li&gt;초기에 많이 사용되고 더이상 사용하지 않을 페이지가 메모리에 남아있을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MFU (Most Frequently Used)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;가장 최근에 사용된 페이지는 카운팅 횟수가 적을 것이라는 판단 하에, 카운트 값이 가장 큰 페이지를 victim으로 지정하고 교체하는 방법이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;LRU Approximation 알고리즘&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;위에서 우리는 counter와 stack을 사용한 LRU 페이지 교체를 살펴보았다. 하지만 현실에서는 이를 구현하기 위해 완벽하게 하드웨어를 지원하는 시스템은 거의 존재하지 않는다. 따라서 우리는 reference-bit를 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Reference bit&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;페이지에 접근할 때마다 하드웨어에 의해서 설정된다.&lt;/li&gt;
&lt;li&gt;운영체제에 의해 초기값은 모두 0으로 설정된다.&lt;/li&gt;
&lt;li&gt;우리는 reference bit를 통하여 어떤 페이지가 참조되었는지 알 수 있지만, 참조된 순서는 알 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Additional-Reference-Bits 알고리즘&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Additional-Reference-Bits&lt;/span&gt;&lt;/b&gt; 알고리즘은 페이지 테이블의 페이지마다 8비트의 reference bit를 가지며, 특정 시간 간격마다 reference bit의 값을 기록한다. &lt;span style=&quot;color: #ee2323;&quot;&gt;Reference bit의 값을 기록할 때는 기존의 값을 right shift 하고, MSB에 reference bit의 값을 기록한다&lt;/span&gt;. 이 비트값을 사용하여 페이지를 사용한 시간으로 해석할 수 있으며, 비트값이 가장 작은 페이지가 victim이 된다. 하지만 단점으로는 가장 작은 비트값이 두 개 이상 존재할 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwS2A9/btqBHyztzI3/E9slRV3ibKgtme4kAxonFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwS2A9/btqBHyztzI3/E9slRV3ibKgtme4kAxonFK/img.png&quot; data-alt=&quot;특정 시간 간격마다 기록되는 Reference bit&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwS2A9/btqBHyztzI3/E9slRV3ibKgtme4kAxonFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwS2A9%2FbtqBHyztzI3%2FE9slRV3ibKgtme4kAxonFK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;특정 시간 간격마다 기록되는 Reference bit&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Second-Chance 알고리즘&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Second-Chance&lt;/span&gt;&lt;/b&gt; 알고리즘은 이름 그대로 두 번의 기회를 주는 것이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;기본적으로 reference bit가 0인 페이지를 victim으로 선택하며, reference bit가 1인 경우에는 0으로 설정하고 페이지에 접근한 시간을 업데이트한다. 그 후에 페이지를 교체하지 않고 다음 페이지부터 다시 탐색을 시작한다&lt;/span&gt;. 만약 모든 reference bit가 1인 경우에는 FIFO 페이지 교체와 같아진다.&lt;/p&gt;
&lt;p&gt;Seconde-Chance 알고리즘은 주로 circular 큐를 사용하여 구현된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bK4usx/btqBEz06v58/6G9UwuakpI8OTdET9hg1lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bK4usx/btqBEz06v58/6G9UwuakpI8OTdET9hg1lk/img.png&quot; data-alt=&quot;Second Chance 알고리즘의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bK4usx/btqBEz06v58/6G9UwuakpI8OTdET9hg1lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbK4usx%2FbtqBEz06v58%2F6G9UwuakpI8OTdET9hg1lk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Second Chance 알고리즘의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Enhanced Second-Chance 알고리즘&lt;/h3&gt;
&lt;p&gt;Enhanced Second-Chance 알고리즘은 &lt;span style=&quot;color: #006dd7;&quot;&gt;reference bit&lt;/span&gt;만 고려하는게 아니라, &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;modify bit&lt;/b&gt;&lt;/span&gt;도 추가하여 함께 고려한다. Reference bit는 페이지를 참조할 때 기록되는 반면, modify bit는 페이지의 내용을 수정할 때 기록된다. 우리는 페이지의 상태를 알기 위해 &lt;span style=&quot;color: #333333;&quot;&gt;이 두 개의 비트를 가지고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;다음과 같이 페이지 상태를 나타낼 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;(Reference bit, Modify bit)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;(0, 0):&lt;/b&gt; Second-Chance 알고리즘을 통해 참조한 지 오래되었지만, 값이 수정된 적이 없음 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;(BEST)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;(0, 1):&lt;/b&gt; Second-Chance 알고리즘을 통해 참조한 지 오래되었지만, 값이 수정되었음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;(1, 0):&lt;/b&gt; 최근에 참조되었으며, 값이 수정된 적이 없음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;(1, 1):&lt;/b&gt; 최근에 참조되었으며, 값이 수정되었음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Enhanced Second-Chance&lt;/span&gt;&lt;/b&gt; 알고리즘은 위의 값들 중에서, &lt;span style=&quot;color: #ee2323;&quot;&gt;가장 낮은 값을 victim으로 선택하며, 최대 3번의 순회를 통해 victim을 구할 수 있다&lt;/span&gt;. 방법은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;상태가 (0, 0)인 페이지를 찾아서 교체한다.&lt;/li&gt;
&lt;li&gt;첫 번째 순회에서 victim 페이지를 찾지 못했다면 상태가 (0, 0)과 (0, 1)인 페이지를 찾아서 교체한다. 순회하면서 &lt;span style=&quot;color: #006dd7;&quot;&gt;reference bit&lt;/span&gt;는 모두 0으로 만든다.&lt;/li&gt;
&lt;li&gt;두 번째 순회에서 victim 페이지를 찾지 못했다면 페이지의 상태는 모두 (0, 0) 또는 (0, 1)만 남게된다. 그럼 다시 상태가 (0, 0)인 페이지를 찾아서 교체한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위와 같은 방법으로 victim 페이지를 찾으면 적어도 세 번째 순회가 끝날 때에는 모든 페이지의 상태가 (0, 0)이 되므로 victim을 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Thrashing (쓰레싱)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;우리는 프로세스에게 메모리 공간을 할당할 때 다음과 같은 이슈가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템이 요구하는 최소의 프레임&lt;/li&gt;
&lt;li&gt;프로세스에게 메모리를 할당하는 방법 (균등하게 vs 상대적으로 다르게)&lt;/li&gt;
&lt;li&gt;Global replacement vs. Local replacement
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;Global replacement:&lt;/b&gt; victim을 찾을 때 메모리 전체에서 찾겠다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Local replacement:&lt;/b&gt; victim을 찾을 때 해당 프로세스가 소유한 프레임 중에서 찾겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;만약 프로세스를 실행하기 위한 충분한 프레임을 지속적으로 확보하지 못한다면 &lt;span style=&quot;color: #006dd7;&quot;&gt;Page Fault&lt;/span&gt;는 급격하게 증가할 것&lt;/span&gt;이고, 이를 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Thrashing&lt;/b&gt;&lt;/span&gt;이라 한다. Thrashing을 일으키는 시나리오는 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;멀티프로그래밍의 degree를 증가시킨다.&lt;/li&gt;
&lt;li&gt;한 개의 프로그램이 추가적인 프레임을 요구하고, 이를 해결하기 위해 &lt;b&gt;전역적으로&lt;/b&gt; 페이지를 교체한다.&lt;/li&gt;
&lt;li&gt;다른 프로그램 또한 추가적인 프레임을 요구하게 되고, &lt;span style=&quot;color: #006dd7;&quot;&gt;Page Fault&lt;/span&gt;가 발생한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Page Fault&lt;/span&gt;가 증가함에따라 &lt;span style=&quot;color: #006dd7;&quot;&gt;디스크 I/O 작업&lt;/span&gt;이 증가하기 때문에 &lt;span style=&quot;color: #006dd7;&quot;&gt;CPU utilization&lt;/span&gt;이 감소한다.&lt;/li&gt;
&lt;li&gt;CPU 스케줄러는 &lt;span style=&quot;color: #006dd7;&quot;&gt;CPU utilization&lt;/span&gt;이 감소하였기 때문에, 이를 보완하기 위해 다시 멀티프로그래밍의 degree를 증가시킨다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgoQ7k/btqBHyztOps/7g5TcAwSu3igz0sekzdxa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgoQ7k/btqBHyztOps/7g5TcAwSu3igz0sekzdxa0/img.png&quot; data-alt=&quot;Thrashing을 나타내는 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgoQ7k/btqBHyztOps/7g5TcAwSu3igz0sekzdxa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgoQ7k%2FbtqBHyztOps%2F7g5TcAwSu3igz0sekzdxa0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Thrashing을 나타내는 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>컴퓨터공학/운영체제</category>
      <category>Additional Reference Bit Algorithm</category>
      <category>Copy on Write</category>
      <category>Demand Paging</category>
      <category>FIFO Page Replacement</category>
      <category>LRU Page Replacement</category>
      <category>Optimal Page Replacement</category>
      <category>page fault</category>
      <category>Page Replacement</category>
      <category>Second Chance Algorithm</category>
      <category>virtual memory</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/73</guid>
      <comments>https://empty-cloud.tistory.com/73#entry73comment</comments>
      <pubDate>Sun, 2 Feb 2020 06:31:32 +0900</pubDate>
    </item>
    <item>
      <title>[Java] JVM이란?</title>
      <link>https://empty-cloud.tistory.com/72</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;JVM이란?&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;JVM이란 &lt;b&gt;Java Virtual Machine&lt;/b&gt;의 약자이다. 즉, 자바 애플리케이션을 실행하기 위한 가상 머신이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;JVM은 컴파일된 자바의 소스코드를 읽어 들이고, &lt;span style=&quot;color: #ee2323;&quot;&gt;Java API를 통하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;운영체제와 Java의 중간자 역할로써 운영체제마다 다른 system call을 사용하여 운영체제가 다르더라도 동일한 연산을 수행할 수 있다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OQEhm/btqBzQ2VBK2/hgvnMVg24wJBRKGryBtdj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OQEhm/btqBzQ2VBK2/hgvnMVg24wJBRKGryBtdj0/img.png&quot; data-alt=&quot;자바 프로그램의 실행 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OQEhm/btqBzQ2VBK2/hgvnMVg24wJBRKGryBtdj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOQEhm%2FbtqBzQ2VBK2%2FhgvnMVg24wJBRKGryBtdj0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자바 프로그램의 실행 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;자바 프로그램의 실행 과정은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Java 컴파일러는 소스코드(.java)를 읽어서 바이트 코드(.class)로 변환한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Class Loader&lt;/span&gt;는 변환된 바이트 코드(.class)를 JVM의 &lt;span style=&quot;color: #006dd7;&quot;&gt;Runtime Data Area&lt;/span&gt;로 로딩한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Exeuction Engine&lt;/span&gt;은 로딩된 바이트 코드(.class)를 해석한다. (해석하는 방법에는 &lt;span style=&quot;color: #006dd7;&quot;&gt;Interpreter&lt;/span&gt;와 &lt;span style=&quot;color: #006dd7;&quot;&gt;JIT Compiler&lt;/span&gt;&amp;nbsp;두 가지 방식이 있다.)&lt;/li&gt;
&lt;li&gt;필요에 따라 &lt;span style=&quot;color: #006dd7;&quot;&gt;Thread Synchronization&lt;/span&gt;과 &lt;span style=&quot;color: #006dd7;&quot;&gt;Garbage Collection&lt;/span&gt;이 이루어진다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Class Loader (클래스 로더)&lt;/h3&gt;
&lt;p&gt;Java는 동적으로 클래스를 읽어오므로, 프로그램이 실행되는 런타임에서야 프로그램의 모든 코드가 JVM의 &lt;span style=&quot;color: #006dd7;&quot;&gt;Runtime Data Area&lt;/span&gt;로 로딩&amp;amp;링킹 된다. 이러한 역할을 하는 것이 Class Loader이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Runtime Data Area (런타임 데이터 영역)&lt;/h3&gt;
&lt;p&gt;Runtime Data Area는 JVM이 운영체제 위해서 프로그램을 실행하기 위해 할당받는 메모리 영역이다. 런타임 데이터 영역은 다음과 같이 5가지 영역으로 나뉠 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;스레드가 공유하는 영역&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Heap &lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;new 명령어로 생성된 모든 객체와 배열이 저장되는 공간. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Garbage Collection의 대상이 되는 공간이다&lt;/span&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;클래스의 정보, 변수의 이름이나 타입, 메소드의 이름이나 리턴 타입, static 변수, 상수 등이 저장되는 공간.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스레드가 공유하지 않는 영역 (= 스레드마다 가지고 있는 영역)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;PC Register&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;CPU의 Program Counter와 유사하며, JVM의 현재 인스트럭션의 주소가 저장된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Stack&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;각 메소드가 실행될 때마다 스택 프레임이 생성되는 스택 영역이다. 메소드가 실행하면서 사용하는 매개변수, 지역변수, 리턴 값 등이 저장되며, 메소드 실행이 끝나면 스택 프레임은 이 영역에서 제거된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Heap 영역에 있는 객체를 가리키는 레퍼런스 변수가 Stack에 저장된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Native Method Stack&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;Java가 아닌 다른 언어로 작성된 코드를 위한 공간이다. JNI(Java Native Interface)를 통해 다른 언어의 코드를 실행하여 커널에 접근할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;719&quot; height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DjpXh/btqBzQvfCCh/sdFnM2k8U3RO1FsRNDdxOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DjpXh/btqBzQvfCCh/sdFnM2k8U3RO1FsRNDdxOk/img.png&quot; data-alt=&quot;Runtime Data Area의 논리적 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DjpXh/btqBzQvfCCh/sdFnM2k8U3RO1FsRNDdxOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjpXh%2FbtqBzQvfCCh%2FsdFnM2k8U3RO1FsRNDdxOk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;719&quot; height=&quot;704&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Runtime Data Area의 논리적 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Execution Engine (실행 엔진)&lt;/h3&gt;
&lt;p&gt;클래스 로더를 통해 JVM의 런타임 데이터 영역에 배치된 바이트 코드는 Exeuction Engine에 의해 실행된다. Execution Engine은 바이트 코드를 명령어 단위로 읽어서 실행한다. 하지만 바이트 코드는 기계가 바로 수행할 수 있는 언어보다는 비교적 인간이 보기 편한 형태이기 때문에, Execution Engine은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 기계어로 번역하며, 방식은 다음과 같이 두 가지가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Interpreter (인터프리터)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;바이트 코드의 인스트럭션을 한 줄씩 읽어서 해석하고 실행한다.&lt;/li&gt;
&lt;li&gt;한 줄씩 해석하고 실행하기 때문에 바이트 코드의 각 명령어의 실행은 빠르지만, 프로그램 전체의 실행 결과는 느리다는 단점을 가지고 있다.&lt;/li&gt;
&lt;li&gt;바이트 코드는 기본적으로 인터프리터 방식으로 동작한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;JIT(Just-In-Time) Compiler&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;인터프리터의 단점을 보완하기 위해 도입되었다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 번역하고, 이후에는 해당 바이트 코드를 더 이상 번역하지 않고 기계어로 직접 실행하는 방식이다.&lt;/li&gt;
&lt;li&gt;기계어를 실행하는 것이 한 줄씩 인터프리팅 하는 것보다 빠르고, 기계어는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;실행 엔진에서 메모리를 효율적으로 관리하기 위해 Garbage Collection을 실행한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Garbage Collection&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;Garbage Collection은 메모리 누수와 같이 &lt;b&gt;프로그램이 필요하지 않은 메모리를 계속 점유하고 있는 상황에서 Garbage Collector가 주기적으로 메모리를 해제하는 행위이다&lt;/b&gt;. &lt;span style=&quot;color: #ee2323;&quot;&gt;이때 Garbage Collection의 대상이 되는 영역은 &lt;b&gt;Heap 영역&lt;/b&gt;이다&lt;/span&gt;. 따라서 개발자가 따로 메모리를 관리하지 않아도 된다.&lt;/p&gt;
&lt;p&gt;Garbage Collection을 수행하는 과정을 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Mark &amp;amp; Sweep&lt;/span&gt;&lt;/b&gt;이라고 부른다. 다음의 과정을 살펴보자.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;메소드 하나가 실행되면서, Stack과 Heap에 필요한 정보를 저장한다. (예: 변수, 동적 할당)&lt;/li&gt;
&lt;li&gt;실행 도중, 더 이상 사용하지 않는 메모리 공간이 발생한다.&lt;/li&gt;
&lt;li&gt;GC(= Garbage Collector)는 Stack 영역을 스캔하면서 현재 Stack 영역의 변수가 참조하고 있는 Heap 영역의 부분을 표시한다. 만약 Heap 영역의 객체가 다른 객체를 참조하면서 사슬이 형성되면, 참조하는 모든 객체를 표시한다. (Mark)&lt;/li&gt;
&lt;li&gt;GC는 Heap 영역을 스캔하면서 표시되지 않은 부분의 메모리를 해제한다. (Sweep)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p15n3/btqBBgfCzcD/3ZojsuVK7vAhGxseprFTdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p15n3/btqBBgfCzcD/3ZojsuVK7vAhGxseprFTdk/img.png&quot; data-alt=&quot;Garbage Collection의 예. a가 참조하던 Heap 영역의 d와 null 부분의 메모리는 더이상 참조되지 않기 때문에 GC에 의해서 해제된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p15n3/btqBBgfCzcD/3ZojsuVK7vAhGxseprFTdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp15n3%2FbtqBBgfCzcD%2F3ZojsuVK7vAhGxseprFTdk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Garbage Collection의 예. a가 참조하던 Heap 영역의 d와 null 부분의 메모리는 더이상 참조되지 않기 때문에 GC에 의해서 해제된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Mark &amp;amp; Sweep을 수행하기 전에 Garbage Collector를 제외한 모든 스레드는 작업을 중단한다&lt;/span&gt;. 이를 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Stop the world&lt;/span&gt;&lt;/b&gt;라고 부르며, GC의 작업이 끝나면 중단했던 작업을 다시 시작한다. 따라서 GC는 성능과 관련된 이슈를 가지고 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/1230&quot;&gt;https://d2.naver.com/helloworld/1230&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.guru99.com/java-virtual-machine-jvm.html&quot;&gt;https://www.guru99.com/java-virtual-machine-jvm.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/java-virtual-machine-jvm-stack-area/&quot;&gt;https://www.geeksforgeeks.org/java-virtual-machine-jvm-stack-area/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tcpschool.com/java/java_intro_programming&quot;&gt;http://tcpschool.com/java/java_intro_programming&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍 언어/Java</category>
      <category>class loader</category>
      <category>execution engine</category>
      <category>garbage collection</category>
      <category>Interpreter</category>
      <category>Java</category>
      <category>JIT compiler</category>
      <category>jvm</category>
      <category>runtime data area</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/72</guid>
      <comments>https://empty-cloud.tistory.com/72#entry72comment</comments>
      <pubDate>Thu, 30 Jan 2020 03:13:08 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Java란?</title>
      <link>https://empty-cloud.tistory.com/71</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java란?&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;Java는 대표적인 &lt;b&gt;객체지향 프로그래밍 언어(Object-Oriented Language)&lt;/b&gt;이다. 또한, 현재 세계에서 가장 많이 사용되고 있는 프로그래밍 언어이기도 하다. 자바는 주로 다음과 같은 언어로 불린다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Platform Independant Language&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;여기서 플랫폼이라 함은, 운영체제를 의미한다.&lt;/li&gt;
&lt;li&gt;Java 컴파일러는 소스코드를 JVM이 이해할 수 있는 언어인&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;바이트 코드&lt;/span&gt;로 변환한다.&lt;/li&gt;
&lt;li&gt;변환된 바이트 코드는 JVM을 통해 Windows, Linux, Mac OS와 같이 여러 운영체제에서 실행될 수 있다. (이는 &lt;span style=&quot;color: #006dd7;&quot;&gt;이식성(=portability)&lt;/span&gt;을 보장한다.) 단, 해당 운영체제를 지원하는 JVM이 있어야 한다.&lt;/li&gt;
&lt;li&gt;즉, &lt;span style=&quot;color: #ee2323;&quot;&gt;운영체제의 제약을 받지 않는 언어이다&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Object-Oriented Language&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;프로그램이 필요한 정보를 추상화시켜 &lt;span style=&quot;color: #006dd7;&quot;&gt;상태와 행위&lt;/span&gt;를 가진 객체로 만들고, 그 객체들 간의 상호작용을 통해 로직을 구성하는 것을 추구하는 언어이다&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Compiler 언어 vs. Interpreter 언어&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Java는 컴파일 언어와 인터프리터 언어의 특징 모두를 포함하고 있다.&lt;/b&gt; 소스코드가 Java 컴파일러를 통해 바이트 코드로 변환되고(&lt;b&gt;컴파일 언어&lt;/b&gt;), 변환된 바이트 코드는 JVM에 의해 인터프리터 방식으로 실행된다. (&lt;b&gt;인터프리터 언어&lt;/b&gt;)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWnFc/btqBBeIwwIK/P5CFpKWvbt67DmWbPKUvQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWnFc/btqBBeIwwIK/P5CFpKWvbt67DmWbPKUvQk/img.png&quot; data-alt=&quot;Java 컴파일러를 통해 바이트 코드로 변환된 소스코드. 컴파일러 언어의 특징이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWnFc/btqBBeIwwIK/P5CFpKWvbt67DmWbPKUvQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWnFc%2FbtqBBeIwwIK%2FP5CFpKWvbt67DmWbPKUvQk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Java 컴파일러를 통해 바이트 코드로 변환된 소스코드. 컴파일러 언어의 특징이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ODogd/btqBBVaSKWp/KsNWqPnyca4uCowhzEIQ6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ODogd/btqBBVaSKWp/KsNWqPnyca4uCowhzEIQ6k/img.png&quot; data-alt=&quot;동일한 바이트 코드가 여러 운영체제에서 실행될 수 있다. 이 때, 해당 운영체제를 지원하는 JVM이 필요하다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ODogd/btqBBVaSKWp/KsNWqPnyca4uCowhzEIQ6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FODogd%2FbtqBBVaSKWp%2FKsNWqPnyca4uCowhzEIQ6k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동일한 바이트 코드가 여러 운영체제에서 실행될 수 있다. 이 때, 해당 운영체제를 지원하는 JVM이 필요하다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;객체지향 언어의 특징&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Abstraction (추상화)&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;구현하고자 하는 영역에서 불필요한 정보는 숨기고, 공통된 중요한 정보만 표현하여 이해하기 쉽게 모델화 하는 것이다&lt;/b&gt;&lt;/span&gt;. 즉, 객체지향 관점에서 클래스를 정의하는 행위이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;560&quot; height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1VVmu/btqBzPpoC92/hbum5nManjGgw7O5b7vj80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1VVmu/btqBzPpoC92/hbum5nManjGgw7O5b7vj80/img.png&quot; data-alt=&quot;추상화의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1VVmu/btqBzPpoC92/hbum5nManjGgw7O5b7vj80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1VVmu%2FbtqBzPpoC92%2Fhbum5nManjGgw7O5b7vj80%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;560&quot; height=&quot;433&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;추상화의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Encapsulation (캡슐화)&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;정보 은닉&lt;/span&gt;을 통해 코드 내부를 볼 수 없게 만드는 행위이다. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;즉, 자신의 속성과 기능을 한 곳에 모아(=캡슐화하여) 재사용성을 높이고 장기 유지보수성(= maintainability)을 향상시킨다&lt;/span&gt;.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;632&quot; height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ktexm/btqBBVviKCO/9RWzAX2BoZMwsTjI9KnWj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ktexm/btqBBVviKCO/9RWzAX2BoZMwsTjI9KnWj0/img.png&quot; data-alt=&quot;캡슐화가 적용되어있지 않은 예. 변경사항이 생기면 많은 양의 코드가 변경되야 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ktexm/btqBBVviKCO/9RWzAX2BoZMwsTjI9KnWj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKtexm%2FbtqBBVviKCO%2F9RWzAX2BoZMwsTjI9KnWj0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;632&quot; height=&quot;552&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;캡슐화가 적용되어있지 않은 예. 변경사항이 생기면 많은 양의 코드가 변경되야 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;617&quot; height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1iQJd/btqBCm7gLql/qk7bvOJNo0tcM1XsOuYESk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1iQJd/btqBCm7gLql/qk7bvOJNo0tcM1XsOuYESk/img.png&quot; data-alt=&quot;캡슐화가 적용된 예. 외부의 사용자는 닭 객체의 모든 정보를 알 필요가 없어진다. 또한 변경사항이 생길 때 변경될 코드의 양이 적어진다.&amp;amp;amp;nbsp;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1iQJd/btqBCm7gLql/qk7bvOJNo0tcM1XsOuYESk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1iQJd%2FbtqBCm7gLql%2Fqk7bvOJNo0tcM1XsOuYESk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;617&quot; height=&quot;471&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;캡슐화가 적용된 예. 외부의 사용자는 닭 객체의 모든 정보를 알 필요가 없어진다. 또한 변경사항이 생길 때 변경될 코드의 양이 적어진다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이뿐만 아니라 &lt;b&gt;캡슐화는 클래스 간의 낮은 결합도를 유지할 수 있도록 해준다&lt;/b&gt;.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Coupling (결합도)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;하나의 기능을 수행하기 위해 다른 클래스나 모듈에 얼마나 의존적인지 나타낸다&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;결합도가 높은 관계에서 하나의 클래스가 변경되면, 관련된 클래스들 또한 함께 변경되어야 한다. 이는 코드의 복잡도가 높아지고, 이해하기 어려워진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Cohesion (응집도)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;하나의 모듈 내의 요소들이 서로 밀접하게 관련되어있는 정도를 나타낸다&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;이상적으로 독립적인 모듈이 되기 위해서는 응집도가 강해야 한다.&lt;/li&gt;
&lt;li&gt;응집도가 높으면 모듈을 쉽게 이해할 수 있고, 재사용하기 쉬워진다. 유지보수성이 향상된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Inheritance (상속성)&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;상속성은 이미 정의된 상위 클래스의 모든 속성과 연산을 하위 클래스가 물려받는 것을 의미한다&lt;/b&gt;&lt;/span&gt;. 상속을 사용하면 하위 클래스는 상위 클래스의 모든 속성과 연산을 다시 정의하지 않고도 사용할 수 있고, 때에 따라서는 상위 클래스에서 물려받은 속성이나 연산을 변경하거나 새로 추가할 수도 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Polymorphism (다형성)&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다형성은 하나의 객체가 여러 가지 클래스로 해석되어 다른 기능을 수행할 수 있는 능력을 의미한다&lt;/b&gt;&lt;/span&gt;. Java에서는 다형성을 지원하기 위해 오버라이딩, 오버로딩이 가능하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Overriding (오버라이딩)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;부모 클래스의 메소드를 재정의 하는 것을 의미한다&lt;/b&gt;. 이때, 메소드 이름, 매개변수와 반환 값은 부모 클래스와 동일해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Overloading (오버로딩)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;부모 클래스와 같은 이름의 함수 및 메소드를 재정의하여, 매개변수의 타입과 개수에 따라 다르게 호출할 수 있게 하는 것을 의미한다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biGh50/btqBBVvp9mQ/RUnVnVSJOGnOLwFfvfCuyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biGh50/btqBBVvp9mQ/RUnVnVSJOGnOLwFfvfCuyk/img.png&quot; data-alt=&quot;상속과 오버라이딩의 예. 부모클래스의 sound() 메소드를 상속받아 재정의 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biGh50/btqBBVvp9mQ/RUnVnVSJOGnOLwFfvfCuyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiGh50%2FbtqBBVvp9mQ%2FRUnVnVSJOGnOLwFfvfCuyk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상속과 오버라이딩의 예. 부모클래스의 sound() 메소드를 상속받아 재정의 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;오버라이딩 된 함수의 경우, 수행 중에 상위 클래스와 하위 클래스에서 적당한 함수를 동적으로 선택할 수 있다. 다음은 &lt;span style=&quot;color: #006dd7;&quot;&gt;동적 바인딩&lt;/span&gt;의 예이다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public static void main()
{
    Person p = new Person(&quot;A&quot;, &quot;M&quot;);
    Student s = new Student(&quot;B&quot;, &quot;F&quot;, 26);
    Person person;

    person = p;
    person.print() // Person 클래스의 print()가 실행됨. &quot;A의 성별은 M입니다.&quot;

    person = s;
    person.print(); // Student 클래스의 print()가 실행됨. &quot;B의 성별은 F이고, 26살 입니다.&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍 언어/Java</category>
      <category>abstraction</category>
      <category>encapsulation</category>
      <category>inheritance</category>
      <category>Java</category>
      <category>Object-Oriented Language</category>
      <category>Overloading</category>
      <category>Overriding</category>
      <category>Platform Independent Language</category>
      <category>Polmorphism</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/71</guid>
      <comments>https://empty-cloud.tistory.com/71#entry71comment</comments>
      <pubDate>Wed, 29 Jan 2020 20:03:25 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 6] 실전 (3)</title>
      <link>https://empty-cloud.tistory.com/70</link>
      <description>&lt;p&gt;본 포스트에서는 제출한 변경사항을 수정하는 방법과, 제출한 변경사항이 병합되는 과정을 살펴보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;본 포스트는 변경사항을 이미 한 번 제출했다고 가정합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;리뷰 확인하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;우리가 제출한 변경사항에 대해서 코멘트가 달렸네요! 한 번 살펴봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;1854&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p2Gaa/btqBvsApt3c/XCxWKHqTBtPy3rAjzx84Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p2Gaa/btqBvsApt3c/XCxWKHqTBtPy3rAjzx84Ik/img.png&quot; data-alt=&quot;다른 리뷰어들이 남긴 코멘트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p2Gaa/btqBvsApt3c/XCxWKHqTBtPy3rAjzx84Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp2Gaa%2FbtqBvsApt3c%2FXCxWKHqTBtPy3rAjzx84Ik%2Fimg.png&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;1854&quot; data-origin-height=&quot;520&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다른 리뷰어들이 남긴 코멘트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;먼저, 7번 패치셋을 제출하고 나서, Zuul로부터 &lt;b&gt;Verified +1&lt;/b&gt;을 받았습니다. &lt;b&gt;즉, 빌드 테스트가 성공했다는 뜻입니다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;그다음으로 Lajos Katona와 Slawek Kalponski로부터 코멘트를 받았네요. 한 번 클릭해서 자세하게 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boGes6/btqBtWJrdIe/OKEr5yxRe1jz3CO2ngX0y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boGes6/btqBtWJrdIe/OKEr5yxRe1jz3CO2ngX0y0/img.png&quot; data-alt=&quot;코멘트가 달린 커밋메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boGes6/btqBtWJrdIe/OKEr5yxRe1jz3CO2ngX0y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboGes6%2FbtqBtWJrdIe%2FOKEr5yxRe1jz3CO2ngX0y0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코멘트가 달린 커밋메시지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 사진은 제가 작성한 커밋 메시지입니다. 노란색으로 하이라이트 된 부분에 달린 코멘트들을 한 마디로 요약하자면, &lt;b&gt;'커밋 메시지를 이렇게 작성하지 마라'&lt;/b&gt;가 되겠네요... 하하 (쓴웃음)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음으로는 제가 실제로 작성한 코드를 살펴봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;977&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIw0no/btqBxAStMF6/u8c7sIkcIpjFNJZquBrH1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIw0no/btqBxAStMF6/u8c7sIkcIpjFNJZquBrH1k/img.png&quot; data-alt=&quot;코멘트가 달린 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIw0no/btqBxAStMF6/u8c7sIkcIpjFNJZquBrH1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIw0no%2FbtqBxAStMF6%2Fu8c7sIkcIpjFNJZquBrH1k%2Fimg.png&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;977&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코멘트가 달린 코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;코드를 살펴보기 전, 빨간 상자를 확인해주세요. 각 빨간 상자를 보시면 패치셋에 대한 번호가 있습니다. 이를 통해 각 패치의 변경 사항을 살펴볼 수 있습니다. 왼쪽에 보이는 부분은 &lt;b&gt;Base 패치&lt;/b&gt;이고, 오른쪽은 &lt;b&gt;7번 패치&lt;/b&gt;입니다. 즉, &lt;b&gt;Base 패치부터 7번 패치까지 어떻게 변화되었는지 한눈에 확인하는 확인할 수 있습니다&lt;/b&gt;. 오른쪽은 7번 패치에서 달린 코멘트입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;783&quot; height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlz8hK/btqBxBqib5P/Wz11LamzShcKPyDRxkeAxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlz8hK/btqBxBqib5P/Wz11LamzShcKPyDRxkeAxK/img.png&quot; data-alt=&quot;코멘트가 달린 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlz8hK/btqBxBqib5P/Wz11LamzShcKPyDRxkeAxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdlz8hK%2FbtqBxBqib5P%2FWz11LamzShcKPyDRxkeAxK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;783&quot; height=&quot;642&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코멘트가 달린 코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위에서 달린 코멘트를 한 줄로 요약하자면, &lt;b&gt;'이렇게 하는 방법 말고 다른 방법 없어? ~~ 이렇게 말이야'&lt;/b&gt;가 되겠네요. 그 부분에 제가 이해가 되지 않는 부분이 있어서 질문을 했고, 이에 또 다른 리뷰어가 코멘트를 달아주었네요. 두 명의 핵심 리뷰어의 리뷰를 통해 어느 정도 방향이 잡혔으니, 제출한 변경사항을 수정하고 다시 제출해봅시다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제출한 변경사항 수정하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;우리는 이미 변경사항을 제출하기 위해 브랜치를 생성하고, 그 브랜치에서 작업했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4muPH/btqBuwcgnPT/q3Ryi9fiyaCK0S1l8HcLb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4muPH/btqBuwcgnPT/q3Ryi9fiyaCK0S1l8HcLb1/img.png&quot; data-alt=&quot;현재 작업중인 브랜치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4muPH/btqBuwcgnPT/q3Ryi9fiyaCK0S1l8HcLb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4muPH%2FbtqBuwcgnPT%2Fq3Ryi9fiyaCK0S1l8HcLb1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;현재 작업중인 브랜치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;다행히 우리가 이전에 작업하던 &lt;b&gt;bug/1857035&lt;/b&gt; 브랜치 그대로 있네요. 그럼 위에서 리뷰어들이 조언해준 대로 코드를 수정하고 아래의 명령어를 입력해봅시다.&lt;/p&gt;
&lt;pre class=&quot;shell sql&quot;&gt;&lt;code&gt;$ git commit --amend&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lvt3S/btqBuxoDBg1/NtG8sfhOGhgXpeuw3NAStK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lvt3S/btqBuxoDBg1/NtG8sfhOGhgXpeuw3NAStK/img.png&quot; data-alt=&quot;커밋 메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lvt3S/btqBuxoDBg1/NtG8sfhOGhgXpeuw3NAStK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flvt3S%2FbtqBuxoDBg1%2FNtG8sfhOGhgXpeuw3NAStK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;커밋 메시지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;리뷰어들이 조언해준 대로 코드와 커밋 메시지를 수정하고 변경사항을 저장합니다. 여기서 주의해야 할 점은, &lt;b&gt;Closes-Id 줄을 수정하면 안 됩니다.&lt;/b&gt; 이는 Gerrit이 커밋을 구분하기 위한 해쉬를 포함하고 있기 때문에, 이 태그가 포함된 줄을 수정해버리면 Gerrit이 우리의 변경사항을 추적할 수 없게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beRheP/btqBvsG7VYf/Sfot7YS6jizjkGRWuWTtHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beRheP/btqBvsG7VYf/Sfot7YS6jizjkGRWuWTtHK/img.png&quot; data-alt=&quot;로컬환경에 반영된 변경사항&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beRheP/btqBvsG7VYf/Sfot7YS6jizjkGRWuWTtHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeRheP%2FbtqBvsG7VYf%2FSfot7YS6jizjkGRWuWTtHK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로컬환경에 반영된 변경사항&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;커밋이 끝난 후, 리뷰를 위해 아래의 명령어로 Gerrit에 제출합니다.&lt;/p&gt;
&lt;pre class=&quot;shell elixir&quot;&gt;&lt;code&gt;$ git review&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;변경사항 병합하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;위의 과정을 반복하면서 패치를 진행하다 보면, 아래와 같이 핵심 리뷰어들로부터 +2점의 코드 리뷰 점수 또는 +1점의 Workflow 점수를 받을 수 있습니다. (이와 관련한 정보는 &lt;a href=&quot;https://empty-cloud.tistory.com/64&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 확인해주세요)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림9.png&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BOnkw/btqBuQhcR3s/aKN4ZnnE5VRPSDQOcYiMRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BOnkw/btqBuQhcR3s/aKN4ZnnE5VRPSDQOcYiMRK/img.png&quot; data-alt=&quot;핵심 리뷰어들로부터 받은 +2의 코드 리뷰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BOnkw/btqBuQhcR3s/aKN4ZnnE5VRPSDQOcYiMRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBOnkw%2FbtqBuQhcR3s%2FaKN4ZnnE5VRPSDQOcYiMRK%2Fimg.png&quot; data-filename=&quot;그림9.png&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;331&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;핵심 리뷰어들로부터 받은 +2의 코드 리뷰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;2명의 핵심 리뷰어들로부터 코드 리뷰 +2점과&amp;nbsp;Workflow +1점을 받았으니 이제 곧 머지가 될 것 같네요!&lt;/p&gt;
&lt;p&gt;그런데 이게 무슨 일인가요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Recheck&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림10.png&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnqXF8/btqByGSrkJ5/PlGzlR2uktKRO0R1EHkzX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnqXF8/btqByGSrkJ5/PlGzlR2uktKRO0R1EHkzX0/img.png&quot; data-alt=&quot;2명의 핵심 리뷰어들로부터 코드 리뷰 +2를 받았지만 실패한 빌드 테스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnqXF8/btqByGSrkJ5/PlGzlR2uktKRO0R1EHkzX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnqXF8%2FbtqByGSrkJ5%2FPlGzlR2uktKRO0R1EHkzX0%2Fimg.png&quot; data-filename=&quot;그림10.png&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;279&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2명의 핵심 리뷰어들로부터 코드 리뷰 +2를 받았지만 실패한 빌드 테스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;첫 번째 빨간 상자처럼 빌드 테스트가 실패했네요. 저는 제 코드에 문제가 생긴 줄 알았지만, 이에 대해서 알아보니 &lt;b&gt;Zuul이 OpenStack의 모든 프로젝트에 대해 여러 빌드 테스트를 동시에 진행하면서, 서버 환경에 잠재적인 에러를 유발할 수 있다고 합니다.&lt;/b&gt; 이와 같은 경우엔, 그냥 &lt;b&gt;recheck&lt;/b&gt;라는 코멘트를 달면 Zuul은 다시 빌드 테스트를 실행합니다. 위의 사진에서 확인할 수 있다시피, 빌드 테스트가 성공하면 게이트 작업을 실행합니다. 이 게이트 작업을 통과하면 최종적으로 우리의 변경사항이 병합됩니다.&lt;/p&gt;
&lt;p&gt;하지만 이게 쉬운 일은 아닙니다. 한 번의 빌드 테스트가 끝나기까지 서버의 상황에 따라 다르겠지만, 저는 대개 6시간 정도 걸렸던 것 같습니다. 저는 &lt;span style=&quot;color: #333333;&quot;&gt;자주&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;빌드 테스트를 실패했습니다. 아래는 제가 매번 테스트에 실패하면서 recheck 코멘트를 단 흔적입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCLNU8/btqBubl1tqO/ZC5SsctdGgL8On1HjdDwAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCLNU8/btqBubl1tqO/ZC5SsctdGgL8On1HjdDwAk/img.png&quot; data-alt=&quot;실패한 빌드 테스트의 흔적들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCLNU8/btqBubl1tqO/ZC5SsctdGgL8On1HjdDwAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCLNU8%2FbtqBubl1tqO%2FZC5SsctdGgL8On1HjdDwAk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실패한 빌드 테스트의 흔적들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Verified +2&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Zuul이 빌드 테스트부터 게이트 작업까지 성공적으로 완료한다면 우리가 제출한 변경사항은 자동적으로 해당 프로젝트의 master 브랜치로 병합됩니다. 이와 동시에, Zuul은 해당 변경사항에 대해서 Verified +2점의 점수를 부여합니다.&lt;/b&gt; 아래는 제가 마지막 패치셋에서 받은 리뷰 점수들입니다. (Rodolfo Alonso Hernandez 씨의 리뷰 점수는 이전의 패치셋에서 받았습니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpHzGU/btqBt9IDDH1/WVhssoqvrnzUqAuXM2jxsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpHzGU/btqBt9IDDH1/WVhssoqvrnzUqAuXM2jxsK/img.png&quot; data-alt=&quot;가장 마지막 패치셋에 받은 리뷰 점수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpHzGU/btqBt9IDDH1/WVhssoqvrnzUqAuXM2jxsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpHzGU%2FbtqBt9IDDH1%2FWVhssoqvrnzUqAuXM2jxsK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가장 마지막 패치셋에 받은 리뷰 점수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Github&lt;/h3&gt;
&lt;p&gt;우리가 제출한 변경사항이 잘 병합되었는지 확인하기 위해서 &lt;span style=&quot;color: #333333;&quot;&gt;Github의 &lt;/span&gt;OpenStack&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&lt;/span&gt;프로젝트 레포지토리에서 확인할 수 있습니다. (제 경우는 &lt;b&gt;openstack/neutron&lt;/b&gt;입니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림11.png&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;655&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sGgIY/btqBvtF5vCC/s1oDxAoCTKarqtPHssOSIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sGgIY/btqBvtF5vCC/s1oDxAoCTKarqtPHssOSIk/img.png&quot; data-alt=&quot;Github에서 확인할 수 있는 우리가 제출한 변경사항&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sGgIY/btqBvtF5vCC/s1oDxAoCTKarqtPHssOSIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsGgIY%2FbtqBvtF5vCC%2Fs1oDxAoCTKarqtPHssOSIk%2Fimg.png&quot; data-filename=&quot;그림11.png&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;655&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Github에서 확인할 수 있는 우리가 제출한 변경사항&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;축하합니다! 드디어 OpenStack에 첫 기여를 끝내셨네요!&lt;/p&gt;
&lt;p&gt;저에게는 한 달이라는 긴 시간이었지만, 그 과정들을 &lt;span style=&quot;color: #333333;&quot;&gt;이렇게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;정리하면서 저뿐만 아니라 다른 사람들에게도 도움이 되고자 글을 남깁니다.&lt;/p&gt;
&lt;p&gt;후에 OpenStack에 contribution을 하고자 하시는 분들께 많은 도움이 되면 좋겠네요.&lt;/p&gt;
&lt;p&gt;정말 긴 글 읽어주셔서 감사합니다.&lt;/p&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/70</guid>
      <comments>https://empty-cloud.tistory.com/70#entry70comment</comments>
      <pubDate>Mon, 27 Jan 2020 21:01:21 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 6] 실전 (2)</title>
      <link>https://empty-cloud.tistory.com/69</link>
      <description>&lt;p&gt;본 포스트에서는 OpenStack을 로컬 환경에 설치하고, 변경 사항을 제출하는 방법에 대해서 설명하고자 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DevStack&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DevStack이란?&lt;/h3&gt;
&lt;p&gt;DevStack은 git의 master 브랜치의 최신 버전을 기반으로 완전한 OpenStack 환경을 신속하게 띄우는 데 사용되는 확장 가능한 스크립트 모음입니다. DevStack은 개발 환경과 많은 OpenStack 프로젝트의 기능 테스트의 기초로서 상호적으로 사용됩니다. 즉, OpenStack을 쉽게 설치할 수 있도록 도와주는 스크립트라고 생각하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DevStack 설치하기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;주의! DevStack은 설치 중에 시스템의 많은 부분을 변경합니다. 오로지 이 목적으로만 사용되는 서버나 가상 머신에서만 DevStack을 실행하세요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Stack User 추가하기 (Optional)&lt;/h4&gt;
&lt;p&gt;DevStack은 sudo권한이 부여된 비-루트 사용자로 실행되어야 합니다. (&quot;ubuntu&quot; 또는 &quot;cloud-user&quot;와 같은 클라우드 이미지에 대한 표준 로그인은 괜찮습니다.)&lt;/p&gt;
&lt;p&gt;만약 클라우드 이미지를 사용하지 않는다면, DevStack을 실행하기 위해 다음과 같은 별도의 stack 유저를 생성할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ sudo useradd -s /bin/bash -d /opt/stack -m stack&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 사용자가 시스템의 상당 부분을 변경할 것이므로, sudo 권한이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ echo &quot;stack ALL=(ALL) NOPASSWD: ALL&quot; | sudo tee /etc/sudoers.d/stack
$ sudo su - stack&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;DevStack 다운로드하기&lt;/h4&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ git clone https://opendev.org/openstack/devstack
$ cd devstack&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DevStack 레포지토리에는 OpenStack을 설치하는 스크립트와 구성 파일을 위한 템플릿이 포함되어 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;local.conf 생성하기&lt;/h4&gt;
&lt;p&gt;DevStack git 레포지토리의 최상위 경로에 4개의 암호가 있는 local.conf 파일을 생성하세요.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[[local|localrc]]
ADMIN_PASSWORD=secret
DATABASE_PASSWORD=$ADMIN_PASSWORD
RABBIT_PASSWORD=$ADMIN_PASSWORD
SERVICE_PASSWORD=$ADMIN_PASSWORD&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이는 DevStack을 시작하는데 필요한 최소 설정입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;DevStack 레포지토리 내의 &lt;i&gt;samples/&lt;/i&gt; 폴더 안에 local.conf를 위한 예제 파일이 있습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설치 시작하기&lt;/h4&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ ./stack.sh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인터넷 연결 속도에 따라 15~20분이 소요됩니다. 이 과정에서 많은 git tree와 패키지가 설치됩니다.&lt;/p&gt;
&lt;p&gt;DevStack을 설치하면서 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;/opt/stack/&lt;/b&gt;&lt;/span&gt; 경로에 &lt;b&gt;keystone, glance, nova, placement, cinder, neutron 그리고 horizon&lt;/b&gt;이 설치됩니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;다른 프로젝트에 대해서 작업하고자 한다면, &lt;span style=&quot;color: #ee2323;&quot;&gt;Github에서 &lt;/span&gt;해당 프로젝트 레포지토리를 복제하시거나 다른 방법으로 설치해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;변경사항 만들기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;다음으로 진행하기 전에, 작업하고자 하는 프로젝트의 레포지토리 내에서 &lt;a href=&quot;https://empty-cloud.tistory.com/54&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 과정&lt;/a&gt;을 마치고 진행하세요. OpenStack의 경로는 &lt;b&gt;/opt/stack/&lt;/b&gt; 입니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항을 작업할 프로젝트로 이동하기&lt;/h3&gt;
&lt;p&gt;OpenStack은 여러 서브 프로젝트들을 포함하고 있기 때문에, 본인이 작업하고자 하는 프로젝트로 이동해야 합니다. 저는 neutron 프로젝트에서 작업을 할 것이기 때문에, neutron 프로젝트로 이동하겠습니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ cd /opt/stack/neutron&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최신 변경사항으로 업데이트하기&lt;/h3&gt;
&lt;p&gt;로컬 레포지토리가 위와 같이 설정되면, 반드시 다음의 workflow를 사용해야 합니다. 최신 버전의 upstream 변경사항이 반영되어 있는지 확인하세요. 아래의 명령어를 실행하여 최신 버전으로 업데이트하세요.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ git remote update
$ git checkout master
$ git pull --ff-only origin master&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;브랜치 생성하기&lt;/h3&gt;
&lt;p&gt;변경사항을 생성하기 전에, 브랜치를 생성해야 합니다. 작업을 저장할 토픽 브랜치를 생성하고, 그 브랜치로 변경하세요. 만약 blueprint에 대해서 작업 중이라면, 브랜치 이름을 bp/BLUEPRINT으로 생성하세요. 여기서 BLUEPRNIT는 Launchpad내의 blueprint 이름입니다. (예: bp/authentication)&lt;/p&gt;
&lt;p&gt;일반적으로 버그에 대해서 작업할 때에는 &lt;span style=&quot;color: #333333;&quot;&gt;브랜치 이름을 &lt;/span&gt;bug/BUG-NUMBER와 같이 생성합니다. (예: bug/1234567) 아니면&amp;nbsp;Gerrit에서 변경사항에 대한 제목을 나타낼 것이기 때문에, 의미 있는 이름으로 생성하세요. 제 경우 버그 번호는 1857035입니다.&lt;/p&gt;
&lt;p&gt;버그 번호는 버그 페이지에서 아래의 빨간 박스 위치에서 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;865&quot; width=&quot;541&quot; height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmlD5R/btqBvtlGyX5/hkmjf0dH972hTsiZMmm3t1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmlD5R/btqBvtlGyX5/hkmjf0dH972hTsiZMmm3t1/img.png&quot; data-alt=&quot;버그 이슈 번호&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmlD5R/btqBvtlGyX5/hkmjf0dH972hTsiZMmm3t1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmlD5R%2FbtqBvtlGyX5%2Fhkmjf0dH972hTsiZMmm3t1%2Fimg.png&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;865&quot; width=&quot;541&quot; height=&quot;497&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버그 이슈 번호&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;다음의 명령어로 브랜치를 생성할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ git checkout -b TOPIC-BRANCH&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAjTSs/btqBuxoyvmj/sAkZFaHxwDLdERE97WGtt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAjTSs/btqBuxoyvmj/sAkZFaHxwDLdERE97WGtt1/img.png&quot; data-alt=&quot;생성된 브랜치 bug/1857035&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAjTSs/btqBuxoyvmj/sAkZFaHxwDLdERE97WGtt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAjTSs%2FbtqBuxoyvmj%2FsAkZFaHxwDLdERE97WGtt1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성된 브랜치 bug/1857035&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항 작업하기&lt;/h3&gt;
&lt;p&gt;이제 해당 버그를 위한 브랜치로 이동했으니, 해당 버그나 이슈에 대해서 작업합니다. (제 경우에는&amp;nbsp; &lt;b&gt;neutron/tests/functional/cmd/test_netns_cleanup.py&lt;/b&gt;에 대해서 작업했습니다.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항 테스트하기&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.openstack.org/wiki/Testing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 참고하여 변경사항에 대해서 테스트하세요. 저는 tox를 사용합니다. 제가 사용한 명령어는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;shell dockerfile&quot;&gt;&lt;code&gt;$ cd /opt/stack/neutron/neutron/tests/functional/cmd
$ tox -e functional -- test_netns_cleanup.NetnsCleanupTest.test_cleanup_network_namespaces_cleans_dhcp_and_l3_namespaces&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이는 test_netns_cleanup.py 모듈의 NetnsCleanupTest 클래스의 test_cleanup_network_namespace_cleans_dhcp_and_l3_namespaces() 메소드를 테스트합니다. &lt;b&gt;여기서 주의할 점은 tox는 파일의 경로와 클래스, 메소드는 마침표(.)로 구분합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGdROY/btqBvt0joNP/HjFecv5KHvbyxA8iEHNaj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGdROY/btqBvt0joNP/HjFecv5KHvbyxA8iEHNaj1/img.png&quot; data-alt=&quot;테스트 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGdROY/btqBvt0joNP/HjFecv5KHvbyxA8iEHNaj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGdROY%2FbtqBvt0joNP%2FHjFecv5KHvbyxA8iEHNaj1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위와 같이 테스트가 성공적으로 끝났다면 이제 변경사항을 제출할 준비가 됐습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항 제출하기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;변경사항을 제출하기 전에, OpenStack의 커밋 메시지 컨벤션과 관련된 포스트를 읽고 진행해주세요. (&lt;a href=&quot;https://empty-cloud.tistory.com/52&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;와 &lt;a href=&quot;https://empty-cloud.tistory.com/53&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 참고해주세요.)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D8mHk/btqByF0fXhs/YF2qNZyzdOzqPle83rKFoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D8mHk/btqByF0fXhs/YF2qNZyzdOzqPle83rKFoK/img.png&quot; data-alt=&quot;작성한 커밋 메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D8mHk/btqByF0fXhs/YF2qNZyzdOzqPle83rKFoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD8mHk%2FbtqByF0fXhs%2FYF2qNZyzdOzqPle83rKFoK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작성한 커밋 메시지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;대부분의 경우 Git-review가 설치한 Gerrit 커밋 훅에 의해 Change-Id 라인이 자동으로 추가된다는 점에 유의하세요. (&lt;b&gt;가장 첫 번째 커밋에는 Change-Id를 작성하지 않으셔야 합니다.&lt;/b&gt;) 이미 커밋을 했는데 Change-Id가 추가되지 않은 경우, &lt;a href=&quot;https://empty-cloud.tistory.com/54&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Gerrit 설정 단계&lt;/a&gt;를 다시 수행하고 다음의 명령어를 실행하세요. `git commit --amend` 커밋 훅은 실제로 아무 변경을 하지 않더라도 커밋 메시지 수정이 끝나면 Change-Id를 추가합니다. &lt;b&gt;Gerrit이 혼동할 수 있으므로 Change-Id는 절대로 변경하지 마세요.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;변경사항에 대해 작업하고 커밋한 후, 리뷰를 위해 제출하세요.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ git commit -a
$ git review&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제출한 변경사항 확인하기&lt;/h3&gt;
&lt;p&gt;우리가 제출한 변경사항은 실시간으로&amp;nbsp;&lt;a href=&quot;https://review.opendev.org/#/q/status:open&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;에서 확인할 수 있습니다. 제 변경사항은 이미 OpenStack에 병합되었으므로, 다른 사람의 변경사항에 대해서 확인해보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lLcwd/btqBuvxy0yF/k4IQnroC2vzfIBdpkWuZV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lLcwd/btqBuvxy0yF/k4IQnroC2vzfIBdpkWuZV0/img.png&quot; data-alt=&quot;지금까지 제출된 변경사항들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lLcwd/btqBuvxy0yF/k4IQnroC2vzfIBdpkWuZV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlLcwd%2FbtqBuvxy0yF%2Fk4IQnroC2vzfIBdpkWuZV0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;지금까지 제출된 변경사항들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위에서 &quot;Mask the token used to allow access to consoles&quot;라는 변경사항을 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;1790&quot; data-origin-height=&quot;1128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEMu5a/btqBubzzfZO/qN6vUbDN286GJ3I1Koo8Ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEMu5a/btqBubzzfZO/qN6vUbDN286GJ3I1Koo8Ek/img.png&quot; data-alt=&quot;제출한 변경사항 페이지. 리뷰를 위해 사용된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEMu5a/btqBubzzfZO/qN6vUbDN286GJ3I1Koo8Ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEMu5a%2FbtqBubzzfZO%2FqN6vUbDN286GJ3I1Koo8Ek%2Fimg.png&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;1790&quot; data-origin-height=&quot;1128&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;제출한 변경사항 페이지. 리뷰를 위해 사용된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;왼쪽 위의 빨간 상자를 확인하시면, 현재 제출한 변경사항의 번호를 확인할 수 있습니다. 이 분의 변경사항의 번호는 704255입니다. 오른쪽 아래의 빨간 상자를 확인하시면 코드 리뷰 점수와 테스트 결과를 확인할 수 있습니다. 이 분의 변경사항은 현재 통과하지 못한 테스트가 있네요. 이 경우에는 다시 새로운 패치를 작성하고 제출하면 자동으로 다시 Zuul이 테스트하고, 해당 패치에 대해 리뷰 점수를 부여합니다.&lt;/p&gt;
&lt;p&gt;현재 진행 중인 테스트에 대해서는 &lt;a href=&quot;http://zuul.opendev.org/t/openstack/status&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 확인하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P4IOp/btqBuQBvaCf/PQ0jbBqrE2BfYyI84udvAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P4IOp/btqBuQBvaCf/PQ0jbBqrE2BfYyI84udvAK/img.png&quot; data-alt=&quot;제출한 변경사항에 대해 진행중인 테스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P4IOp/btqBuQBvaCf/PQ0jbBqrE2BfYyI84udvAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP4IOp%2FbtqBuQBvaCf%2FPQ0jbBqrE2BfYyI84udvAK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;제출한 변경사항에 대해 진행중인 테스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위에서 말했다시피, 실패한 테스트가 있음을 확인할 수 있습니다. 만약 Zuul의 빌드 테스트를 통과한다면 다음과 같은 이메일을 받으실 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WLAZc/btqByFFXc3c/KN5BrH9Chn9gKUUFRoLqkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WLAZc/btqByFFXc3c/KN5BrH9Chn9gKUUFRoLqkk/img.png&quot; data-alt=&quot;Zuul의 빌드 테스트 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WLAZc/btqByFFXc3c/KN5BrH9Chn9gKUUFRoLqkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWLAZc%2FbtqByFFXc3c%2FKN5BrH9Chn9gKUUFRoLqkk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Zuul의 빌드 테스트 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이제는 우리는 Zuul로부터 빌드 테스트도 통과했고, 변경사항이 병합되기까지 핵심 리뷰어들로부터 +2점의 리뷰를 2번 이상 받기만 하면 됩니다!&lt;/p&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>devstack</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/69</guid>
      <comments>https://empty-cloud.tistory.com/69#entry69comment</comments>
      <pubDate>Mon, 27 Jan 2020 18:13:32 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 6] 실전 (1)</title>
      <link>https://empty-cloud.tistory.com/68</link>
      <description>&lt;p&gt;이번 포스트에서는 OpenStack에 contribute 하기 전에 해결하기 쉬운 버그나 이슈를 찾는 방법에 대해 설명할 것입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;본 포스트는 실제로 제가 OpenStack에 기여하기 위해 진행했던 과정들임을 참고해주시기 바랍니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결하고자 하는 버그 또는 이슈 찾기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;OpenStack에 기여하는 방법은 여러 가지가 존재합니다. 하지만 blueprint에 제시된 새로운 기능을 구현하거나, 양이 많은 패치는 처음 기여를 하는 개발자들에게는 어려운 일입니다. 따라서 우리는 해결하기 쉬운, 간단한 버그부터 찾아보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;먼저, OpenStack의 이슈나 버그들은 현재 대부분 &lt;b&gt;&lt;a href=&quot;https://launchpad.net/openstack&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Launchpad&lt;/a&gt;&lt;/b&gt;를 통해서 보고됩니다. OpenStack에는 매우 많은 프로젝트가 존재하는데요, 여기서 본인이 기여하고자 하는 프로젝트만 고르셔도 되지만, 저는 모든 프로젝트에 대해서 찾아보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btHt2A/btqBtYtAVnG/K9j1CcBlvB2PrOjEUZaFc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btHt2A/btqBtYtAVnG/K9j1CcBlvB2PrOjEUZaFc0/img.png&quot; data-alt=&quot;OpenStack의 Launchpad에 접속했을 때의 메인화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btHt2A/btqBtYtAVnG/K9j1CcBlvB2PrOjEUZaFc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtHt2A%2FbtqBtYtAVnG%2FK9j1CcBlvB2PrOjEUZaFc0%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;535&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OpenStack의 Launchpad에 접속했을 때의 메인화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위의 카테고리에서&amp;nbsp;&lt;b&gt;Bugs&lt;/b&gt; 섹션을 클릭해주세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;765&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Dxta3/btqByFTqDvp/UEgajzBF2VnezX1sxDhnC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Dxta3/btqByFTqDvp/UEgajzBF2VnezX1sxDhnC1/img.png&quot; data-alt=&quot;OpenStack Launchpad의 Bugs 섹션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Dxta3/btqByFTqDvp/UEgajzBF2VnezX1sxDhnC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDxta3%2FbtqByFTqDvp%2FUEgajzBF2VnezX1sxDhnC1%2Fimg.png&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;765&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OpenStack Launchpad의 Bugs 섹션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Bugs 섹션에서 위와 같이 현재 OpenStack 내에서 보고된 모든 이슈와 버그들을 확인할 수 있습니다. 왼쪽에 &lt;span style=&quot;color: #ee2323;&quot;&gt;CRITICAL&lt;/span&gt;과 &lt;span style=&quot;color: #006dd7;&quot;&gt;IN PROGRESS&lt;/span&gt;, &lt;span style=&quot;color: #f3c000;&quot;&gt;CONFIRMED&lt;/span&gt;와 같은 정보를 확인하실 수 있는데요, 이와 같은 정보는 &lt;a href=&quot;https://docs.openstack.org/project-team-guide/bugs.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 참고해주세요. 우리는 여기서 우리가 해결할 수 있는 쉬운 버그를 찾아야 합니다. 위에서 Advanced search를 클릭해주세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4GTJI/btqByFy7IJP/Sg3wkJfWHic2BDroT5i6Lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4GTJI/btqByFy7IJP/Sg3wkJfWHic2BDroT5i6Lk/img.png&quot; data-alt=&quot;Advanced Search 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4GTJI/btqByFy7IJP/Sg3wkJfWHic2BDroT5i6Lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4GTJI%2FbtqByFy7IJP%2FSg3wkJfWHic2BDroT5i6Lk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Advanced Search 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;보고된 각 버그들 중에서, 쉬운 버그를 찾기 위해 위와 같이 체크해주세요. 그리고 스크롤을 아래로 내리다 보면&amp;nbsp;태그를 입력하는 곳이 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cw4pr/btqBxAdKB2L/FT8xFeYRCjgC1xqtGU9F10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cw4pr/btqBxAdKB2L/FT8xFeYRCjgC1xqtGU9F10/img.png&quot; data-alt=&quot;Advanced Search 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cw4pr/btqBxAdKB2L/FT8xFeYRCjgC1xqtGU9F10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCw4pr%2FbtqBxAdKB2L%2FFT8xFeYRCjgC1xqtGU9F10%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Advanced Search 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이 부분이 정말 중요합니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;Tags에 &lt;b&gt;low-hanging-fruit&lt;/b&gt;를 입력해주세요. &lt;/span&gt;이 태그는 저희와 같이 OpenStack에 처음 contribute를 하는 사람들을 위한 태그입니다. 이 태그를 통해 해당 버그나 이슈가 해결하기 쉽다는 것을 초보 기여자들에게 알리고, 그와 동시에 진입장벽을 낮춰 OpenStack에 기여를 할 수 있도록 장려하는 태그입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL2Ohq/btqBuw4fm4E/16MN2NsefvBuhSq2kJFtUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL2Ohq/btqBuw4fm4E/16MN2NsefvBuhSq2kJFtUK/img.png&quot; data-alt=&quot;low-hanging-fruit 태그를 가진 버그와 이슈들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL2Ohq/btqBuw4fm4E/16MN2NsefvBuhSq2kJFtUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL2Ohq%2FbtqBuw4fm4E%2F16MN2NsefvBuhSq2kJFtUK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;low-hanging-fruit 태그를 가진 버그와 이슈들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;여기서 본인이 해결하고자 하는 버그나 이슈를 선택해주세요. 저는 neutron 프로젝트의 버그를 선택했습니다. (&lt;a href=&quot;https://bugs.launchpad.net/neutron/+bug/1857035&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;를 참고해주세요.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;869&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DwhLP/btqBukiFJst/6zROLaLC8ywpBKSKU0y7N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DwhLP/btqBukiFJst/6zROLaLC8ywpBKSKU0y7N1/img.png&quot; data-alt=&quot;보고된 버그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DwhLP/btqBukiFJst/6zROLaLC8ywpBKSKU0y7N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDwhLP%2FbtqBukiFJst%2F6zROLaLC8ywpBKSKU0y7N1%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;869&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보고된 버그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;만약, 해당 버그나 이슈가 본인이 해결할 수 있다고 생각하신다면, 위에서 표시된 빨간 박스 안의 연필 모양을 클릭해서 해당 버그를 본인에게 할당하세요. (&lt;b&gt;주의: 해당 버그가 이미 누군가에게 할당되어 있다면, 코멘트를 통해서 미리 그 사람과 상의한 후에 본인에게 할당하세요. 아무 상의 없이 본인에게 할당한다면 상대방의 기회를 뺐는 무례한 행동입니다.&lt;/b&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzr89C/btqBvtsqTD2/jcaPwLUExOwC01Wjy5CwAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzr89C/btqBvtsqTD2/jcaPwLUExOwC01Wjy5CwAK/img.png&quot; data-alt=&quot;버그 페이지에 달린 코멘트. 해당 버그가 본인에게 할당된 것을 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzr89C/btqBvtsqTD2/jcaPwLUExOwC01Wjy5CwAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzr89C%2FbtqBvtsqTD2%2FjcaPwLUExOwC01Wjy5CwAK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버그 페이지에 달린 코멘트. 해당 버그가 본인에게 할당된 것을 확인할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위와 같이 해당 버그 페이지의 코멘트를 통해 본인에게 할당된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>launchpad</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/68</guid>
      <comments>https://empty-cloud.tistory.com/68#entry68comment</comments>
      <pubDate>Mon, 27 Jan 2020 15:06:38 +0900</pubDate>
    </item>
    <item>
      <title>[운영체제] 메모리 관리 (2)</title>
      <link>https://empty-cloud.tistory.com/67</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Fragmentation (단편화)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;External fragmentation (외부 단편화)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;프로세스를 실행하기 위한 메모리 공간이 physical 메모리 내에 존재하지만, 연속적이지 않아서 할당할 수 없는 상황&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Internal fragmentation (내부 단편화)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;프로세스를 실행하기 위해 메모리가 할당됐지만, 프로세스가 필요한 양보다 더 많이 할당되어 프로세스에게 할당된 메모리가 낭비되는 상황&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;939&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w6weJ/btqBp4Oelze/9kk7sjr0CQ1CcyGRkIrdy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w6weJ/btqBp4Oelze/9kk7sjr0CQ1CcyGRkIrdy0/img.png&quot; data-alt=&quot;External fragmentation과 Internal fragmentation&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w6weJ/btqBp4Oelze/9kk7sjr0CQ1CcyGRkIrdy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw6weJ%2FbtqBp4Oelze%2F9kk7sjr0CQ1CcyGRkIrdy0%2Fimg.png&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;939&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;External fragmentation과 Internal fragmentation&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;50-percent rule&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;First-fit을 통계적으로 분석해보면, &lt;span style=&quot;color: #ee2323;&quot;&gt;만약 메모리 내에서 N개의 블록이 할당되었을 때, 0.5N개의 블록이 internal fragmentation으로 손실될 수 있다&lt;/span&gt;. 즉, 1.5N개의 블록 중 0.5N개가 손실되므로, 메모리의 1/3을 쓸 수 없게 될 수 있다는 것을 의미한다. 이러한 현상을 &lt;b&gt;50-percent rule&lt;/b&gt;이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Solutions to External Fragmentation (외부 단편화의 해결방법)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Compaction (압축)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;외부 단편화&lt;/span&gt;로 분산되어 있는 메모리 공간들을 재배치하여, 하나의 큰 메모리 공간으로 확보한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Paging (페이징)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;가상 메모리를 사용하여&lt;/b&gt;&lt;/u&gt; 프로세스를 크기가 같은 블록인 &lt;span style=&quot;color: #006dd7;&quot;&gt;페이지&lt;/span&gt;로 나누고, 물리 메모리도 페이지의 크기와 동일한 &lt;span style=&quot;color: #006dd7;&quot;&gt;프레임&lt;/span&gt;으로 나눈다. 페이지와 프레임을 대응하여 연속적인 물리 메모리가 아니더라도 프로세스가 필요한 만큼의 프레임을 사용할 수 있도록 하는 기법. 연속적이지 않은 메모리 공간을 활용하기 때문에 &lt;span style=&quot;color: #006dd7;&quot;&gt;외부 단편화&lt;/span&gt;를 해결한다. 하지만 고정된 크기의 프레임을 할당하기 때문에 &lt;span style=&quot;color: #006dd7;&quot;&gt;내부 단편화&lt;/span&gt;가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;작은 크기의 페이지를 사용하면 내부 단편화를 줄일 수 있지만, 페이지 테이블 내의 엔트리가 증가하고, 이는 더 큰 오버헤드를 유발한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Page (페이지)&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;논리 메모리를 일정한 크기로 나눈 블록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Frame (프레임)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;물리 메모리를 일정한 크기로 나눈 블록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;493&quot; width=&quot;706&quot; height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctG0ZO/btqBqPi5stZ/Yuj1AHCLzQeH6HbNVCb00K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctG0ZO/btqBqPi5stZ/Yuj1AHCLzQeH6HbNVCb00K/img.png&quot; data-alt=&quot;Paging을 사용한 주소 변환&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctG0ZO/btqBqPi5stZ/Yuj1AHCLzQeH6HbNVCb00K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctG0ZO%2FbtqBqPi5stZ%2FYuj1AHCLzQeH6HbNVCb00K%2Fimg.png&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;493&quot; width=&quot;706&quot; height=&quot;326&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Paging을 사용한 주소 변환&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;CPU는 &lt;b&gt;논리적 주소&lt;/b&gt;인 p와 d를 생성하는데, p는 page number, d는 page offset을 의미한다. 페이지의 크기는 하드웨어에 의해서 결정되는데, 주로 2의 지수형태이다. &lt;b&gt;페이지는 페이지 테이블을 통해 실제 물리 메모리의 주소로 매핑된다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;1071&quot; data-origin-height=&quot;472&quot; width=&quot;601&quot; height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WxqSm/btqBtMlDbr6/wcDjvTxNIemn3GMkjnkGB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WxqSm/btqBtMlDbr6/wcDjvTxNIemn3GMkjnkGB0/img.png&quot; data-alt=&quot;Paging의 논리적 주소&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WxqSm/btqBtMlDbr6/wcDjvTxNIemn3GMkjnkGB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWxqSm%2FbtqBtMlDbr6%2FwcDjvTxNIemn3GMkjnkGB0%2Fimg.png&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;1071&quot; data-origin-height=&quot;472&quot; width=&quot;601&quot; height=&quot;265&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Paging의 논리적 주소&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;864&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tDNbM/btqBqOj8tkO/dMr35wJBaNXizHUdoEGr21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tDNbM/btqBqOj8tkO/dMr35wJBaNXizHUdoEGr21/img.png&quot; data-alt=&quot;Paging의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tDNbM/btqBqOj8tkO/dMr35wJBaNXizHUdoEGr21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtDNbM%2FbtqBqOj8tkO%2FdMr35wJBaNXizHUdoEGr21%2Fimg.png&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;864&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Paging의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Hardware Support for Paging&lt;/h4&gt;
&lt;p&gt;페이지 테이블을 만드는 대표적인 방법으로 다음과 같이 2가지가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU 내에 페이지 테이블을 만들기&lt;/li&gt;
&lt;li&gt;메모리 내에 페이지 테이블을 만들기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;첫 번째는 CPU 내부에 레지스터로 페이지 테이블을 만드는 것이다. 이는 &lt;b&gt;주소변환을 빠르게 할 수 있지만, CPU가 사용할 수 있는 레지스터는 한정되어 있으므로 페이지 테이블의 크기가 매우 제한된다는 단점이 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;두 번째는 메모리 내부에 페이지 테이블을 만드는 것이다. 이는 첫 번째와 반대로 &lt;b&gt;페이지 테이블의 크기에 제한이 없지만, 주소 변환 속도가 느리다는 단점이 있다.&lt;/b&gt; CPU는 프로세스에 접근하기 위해서 물리 메모리 내에 있는 페이지 테이블에 접근하고, 이 페이지 테이블을 다시 참조하여 물리 메모리 내의 &lt;span style=&quot;color: #333333;&quot;&gt;실제 프로세스&lt;/span&gt;&amp;nbsp;주소로 접근하는데, 이는 &lt;b&gt;2번의 메모리 접근&lt;/b&gt;을 하는 것이므로 매우 느리다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림7.png&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcWF0f/btqBr8I70qz/bIuyKfpccsE7OTXRkAl5k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcWF0f/btqBr8I70qz/bIuyKfpccsE7OTXRkAl5k1/img.png&quot; data-alt=&quot;페이지 테이블을 만드는 2가지 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcWF0f/btqBr8I70qz/bIuyKfpccsE7OTXRkAl5k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcWF0f%2FbtqBr8I70qz%2FbIuyKfpccsE7OTXRkAl5k1%2Fimg.png&quot; data-filename=&quot;그림7.png&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;514&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;페이지 테이블을 만드는 2가지 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 두 가지 방법은 장단점이 너무 상반되기 때문에, 이를 해결하기 위해 &lt;b&gt;페이지 테이블을 위한 캐시&lt;/b&gt;를 만들었다. 즉, 별도의 하드웨어를 둔 것이다. 이 하드웨어를 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;TLB(Translation look-aside buffer)&lt;/b&gt;&lt;/span&gt;라고 부른다. TLB는 &lt;span style=&quot;color: #ee2323;&quot;&gt;CPU 내에 페이지 테이블을 두는 것보다 크기가 더 크고, 메모리 내에 페이지 테이블을 두는 것보다 주소 변환 속도가 더 빠르다는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XucOz/btqBtXl6VXN/nQqJG9Z8WsgL3HnxIcqvi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XucOz/btqBtXl6VXN/nQqJG9Z8WsgL3HnxIcqvi0/img.png&quot; data-alt=&quot;TLB를 사용한 주소 변환&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XucOz/btqBtXl6VXN/nQqJG9Z8WsgL3HnxIcqvi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXucOz%2FbtqBtXl6VXN%2FnQqJG9Z8WsgL3HnxIcqvi0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;TLB를 사용한 주소 변환&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Page Protection&lt;/h4&gt;
&lt;p&gt;프로세스의 모든 주소는 페이지 테이블을 경유하므로, 페이지 테이블을 이용해서 보호 기능을 수행할 수 있다. 대표적으로 valid-invalid bit를 두고, 해당 비트가 유효할 때만 프레임에 접근하도록 하는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VOTYH/btqBqOEESQf/D0qZISNRakyWG3d72xdyXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VOTYH/btqBqOEESQf/D0qZISNRakyWG3d72xdyXK/img.png&quot; data-alt=&quot;page protection의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VOTYH/btqBqOEESQf/D0qZISNRakyWG3d72xdyXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVOTYH%2FbtqBqOEESQf%2FD0qZISNRakyWG3d72xdyXK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;page protection의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Page Sharing&lt;/h4&gt;
&lt;p&gt;프로세스는 code + data + stack + heap의 구조를 가지고 있다. 하나의 프로그램에서 여러 프로세스가 동일한 code를 사용한다면, 하나의 code 영역을 공유함으로써 메모리의 낭비를 줄일 수 있다. 하지만 이때 조건은, &lt;b&gt;code는 &lt;span style=&quot;color: #006dd7;&quot;&gt;reentrant&lt;/span&gt;(= read only) 해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;1614&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zh590/btqBuaS9jxu/zLFHDgnTKzkxB6TzYQO7u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zh590/btqBuaS9jxu/zLFHDgnTKzkxB6TzYQO7u0/img.png&quot; data-alt=&quot;Page sharing의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zh590/btqBuaS9jxu/zLFHDgnTKzkxB6TzYQO7u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzh590%2FbtqBuaS9jxu%2FzLFHDgnTKzkxB6TzYQO7u0%2Fimg.png&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;1614&quot; data-origin-height=&quot;800&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Page sharing의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Page Table Structure&lt;/h4&gt;
&lt;p&gt;32비트 시스템은&amp;nbsp;&lt;b&gt;2^32(= 4GB)&lt;/b&gt;만큼의 주소 공간을 가진다. 여기서 페이지의 크기가 &lt;b&gt;4KB(= 2^12)&lt;/b&gt;라고 가정하면, 페이지 테이블이 가질 수 있는 페이지의 개수는 &lt;b&gt;1MB(= 2^20, 약 100만 개)이다.&lt;/b&gt; 32비트 시스템에서 페이지를 나타내는 주소는 32비트(= &lt;b&gt;4B&lt;/b&gt;)이므로, &lt;b&gt;프로세스당 페이지 테이블의 크기는 4B * 1MB = 4MB (= 2^22)&lt;/b&gt;이다.&lt;/p&gt;
&lt;p&gt;이렇게 생성된 페이지 테이블들은 프로그램이 메모리에 적재될 때 함께 적재된다. 하지만 페이지 테이블은 4MB로써 매우 큰 크기를 가진다. &lt;span style=&quot;color: #ee2323;&quot;&gt;이때 페이지 테이블은 연속적으로 메모리에 적재되므로 단편화로 인해 메모리 공간을 낭비하게 된다.&lt;/span&gt; 이를 해결하기 위해 다음과 같은 구조를 제시한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Hierarchical Paging (계층적 페이징)&lt;/li&gt;
&lt;li&gt;Hashed Page Table (해쉬 페이지 테이블)&lt;/li&gt;
&lt;li&gt;Inverted Page Table (역 페이지 테이블)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Hierarchical Paging (계층적 페이징)&lt;/h4&gt;
&lt;p&gt;4MB의 연속된 메모리 공간은 생각보다 크다. 심지어 프로세스 또한 그 주소 공간 중 아주 일부분만 사용하므로, 페이지 테이블의 아주 일부분에만 접근할 것이다. 우리가 메모리 내에서 낭비되는 주소 공간을 페이징으로 해결한 것처럼, 페이지 테이블 내에서 낭비되는 공간 또한 페이징으로 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;계층적 페이징은 기존의 페이지 테이블 내의 페이지를 참조하는 또 다른 페이지 테이블(=outer page table)을 두어, 페이지 테이블을 비연속적으로 만드는 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;862&quot; width=&quot;666&quot; height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvQ3Yp/btqBtLUxTzv/pXBraPk9wLeptSfhPvb6r0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvQ3Yp/btqBtLUxTzv/pXBraPk9wLeptSfhPvb6r0/img.png&quot; data-alt=&quot;Hierarchical paging의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvQ3Yp/btqBtLUxTzv/pXBraPk9wLeptSfhPvb6r0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvQ3Yp%2FbtqBtLUxTzv%2FpXBraPk9wLeptSfhPvb6r0%2Fimg.png&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;862&quot; width=&quot;666&quot; height=&quot;565&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Hierarchical paging의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;32비트 주소체계에서, 기존의 &lt;b&gt;4MB(= 2^22)&lt;/b&gt; 페이지 테이블은 &lt;b&gt;1M(= 2^20)&lt;/b&gt;개의 엔트리를 가진다. &lt;span style=&quot;color: #006dd7;&quot;&gt;Page of page table&lt;/span&gt;의 크기는 기존의 페이지와 동일하게 &lt;b&gt;4KB(= 2^12)&lt;/b&gt;이므로, &lt;b&gt;1K(= 2^10)&lt;/b&gt;개의 엔트리를 가진다. 따라서, 기존의 페이지 테이블 내에 존재하는 &lt;span style=&quot;color: #006dd7;&quot;&gt;page of page table&lt;/span&gt;은 &lt;b&gt;1K(= 2^10)&lt;/b&gt;개가 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Page of page table&lt;/span&gt;이 &lt;b&gt;1K(= 2^10)&lt;/b&gt;개가 존재하므로 &lt;span style=&quot;color: #006dd7;&quot;&gt;outer page table&lt;/span&gt;의 엔트리는 이와 동일하게 &lt;b&gt;1K(= 2^10)&lt;/b&gt;개가 필요하고, 엔트리 한 개는 &lt;span style=&quot;color: #006dd7;&quot;&gt;page of page table&lt;/span&gt;의 주소를 가리키므로 크기는 &lt;b&gt;4KB(= 2^12)&lt;/b&gt;가 된다. 이는 페이지 1개의 크기와 동일하므로 더 이상 페이징으로 나눌 필요가 없게 된다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;위의 그림은 2번의 페이징을 통해 메모리 내의 프레임을 찾는 과정을 나타낸다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림9.png&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;729&quot; width=&quot;596&quot; height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v2zwn/btqBtYzjJIt/uyuFOM3pPVPXOcqZlqD9v1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v2zwn/btqBtYzjJIt/uyuFOM3pPVPXOcqZlqD9v1/img.png&quot; data-alt=&quot;Hierachical paging의 논리적 주소 변환 체계&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v2zwn/btqBtYzjJIt/uyuFOM3pPVPXOcqZlqD9v1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv2zwn%2FbtqBtYzjJIt%2FuyuFOM3pPVPXOcqZlqD9v1%2Fimg.png&quot; data-filename=&quot;그림9.png&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;729&quot; width=&quot;596&quot; height=&quot;299&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Hierachical paging의 논리적 주소 변환 체계&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;32비트 주소 체계에서, 첫 10비트는 어떤 &lt;span style=&quot;color: #006dd7;&quot;&gt;page of page table&lt;/span&gt;을 사용할지 찾는 데 사용된다. 두 번째 10비트는 우리가 메모리 내에서 어떤 프레임을 사용할지 찾는 데 사용된다. 남은 12비트는 프레임 내의 오프셋으로 사용된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Hashed Page Table (해쉬 페이지 테이블)&lt;/h4&gt;
&lt;p&gt;해쉬 페이지 테이블은 32비트 시스템에서 32비트보다 큰 주소를 처리할 때 사용한다. 해시 테이블의 각 항목들은 연결 리스트를 가지고 있다. 가상의 페이지 번호는 해싱되어 테이블에 저장된다. 각 연결 리스트의 항목들은 &lt;b&gt;&amp;lt;가상 페이지 번호, 프레임 번호, 다음 항목을 향한 포인터&amp;gt;&lt;/b&gt;로 이루어져 있다. 해시 테이블로부터 물리 주소를 찾을 때 연결 리스트의 항목들로부터 &lt;b&gt;가상 페이지 번호&lt;/b&gt;와 &lt;b&gt;프레임 번호&lt;/b&gt;를 비교하여, 일치한다면 해당 주소를 반환한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;583&quot; height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bynaQP/btqBukhBjDf/kSiBAvc9H4OOSakJ9c4u9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bynaQP/btqBukhBjDf/kSiBAvc9H4OOSakJ9c4u9K/img.png&quot; data-alt=&quot;Hashed page table의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bynaQP/btqBukhBjDf/kSiBAvc9H4OOSakJ9c4u9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbynaQP%2FbtqBukhBjDf%2FkSiBAvc9H4OOSakJ9c4u9K%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;583&quot; height=&quot;314&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Hashed page table의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Inverted Page Table (역 페이지 테이블)&lt;/h4&gt;
&lt;p&gt;기존의 페이지 테이블은 한 개의 프로세스당 한 개의 페이지 테이블을 가지고 있었다. 만약 프로세스가 많이 존재한다면, 페이지 테이블 또한 메모리에 저장되어 메모리 공간이 그만큼 필요하게 된다. 역 페이지 테이블은 시스템 내에 한 개의 전역 페이지 테이블을 두어 물리 메모리 내의 프레임에 대응하는 항목을 가진다. 이는 물리 메모리에서 실제로 사용되는 프레임만을 항목으로 가지므로 메모리의 낭비를 줄일 수 있지만, 각 프레임들이 어떤 프로세스에 의해서 사용되고 있는지 알기 위해 프로세스 ID가 필요하고, 해당 프레임이 몇 번째 페이지에 해당하는지 알기 위해 페이지 번호 또한 필요하다. 따라서 역 페이지 테이블은 &lt;b&gt;&amp;lt;프로세스 ID, 페이지 번호&amp;gt;&lt;/b&gt;를 저장한다.&lt;/p&gt;
&lt;p&gt;실제 물리 주소를 얻기 위해 &lt;b&gt;&amp;lt;프로세스 ID, 페이지 번호&amp;gt;&lt;/b&gt;가 일치하는 항목을 찾고, 이때의 인덱스가 실제 메모리의 프레임 번호가 된다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;역 페이지 테이블은 메모리 공간을 많이 절약할 수 있지만, 프레임을 찾기 위해 테이블 전체를 검색해야 하므로 Linear search에 대한 오버헤드가 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;554&quot; height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uJ0JD/btqBtWIhSSm/wZBjKobNBtO9P9Li8rLRak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uJ0JD/btqBtWIhSSm/wZBjKobNBtO9P9Li8rLRak/img.png&quot; data-alt=&quot;Inverted page table의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uJ0JD/btqBtWIhSSm/wZBjKobNBtO9P9Li8rLRak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuJ0JD%2FbtqBtWIhSSm%2FwZBjKobNBtO9P9Li8rLRak%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;554&quot; height=&quot;292&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Inverted page table의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Solutions to Internal fragmentation (내부 단편화의 해결방법)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Segmentation (세그멘테이션)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;가상 메모리를 사용하여&lt;/u&gt;&lt;/b&gt; 프로세스를 크기가 &lt;span style=&quot;color: #ee2323;&quot;&gt;서로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;다른 논리적 단위인 &lt;span style=&quot;color: #006dd7;&quot;&gt;세그먼트&lt;/span&gt;로 분할하고 메모리를 할당하여 &lt;span style=&quot;color: #006dd7;&quot;&gt;내부 단편화&lt;/span&gt;를 해결하는 기법. 프로세스를 메모리에 적재시키고 해제함을 반복함으로써 &lt;span style=&quot;color: #006dd7;&quot;&gt;외부 단편화&lt;/span&gt;가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Segment (세그먼트)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;가상 메모리 내에서 서로 크기가 다른 논리적 단위&lt;/li&gt;
&lt;li&gt;각 세그먼트는 이름(또는 숫자)과 길이를 가지고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Segment table (세그먼트 테이블)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;세그먼트들의 정보를 가지고 있는 테이블 &lt;b&gt;&amp;lt;Base address, Limit&amp;gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;테이블 내의 논리 메모리 주소를 1차원 물리 메모리 주소로 매핑한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;2007&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cr1odP/btqBrA6I7Th/yfKgMm7x7EZAoAa7JAa2d0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cr1odP/btqBrA6I7Th/yfKgMm7x7EZAoAa7JAa2d0/img.png&quot; data-alt=&quot;Segmentation의 논리적 관점&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cr1odP/btqBrA6I7Th/yfKgMm7x7EZAoAa7JAa2d0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcr1odP%2FbtqBrA6I7Th%2FyfKgMm7x7EZAoAa7JAa2d0%2Fimg.png&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;2007&quot; data-origin-height=&quot;848&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Segmentation의 논리적 관점&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;461&quot; width=&quot;542&quot; height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwzOYR/btqBp5l0VaZ/K4sP7d5qASXW77KkukVJ9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwzOYR/btqBp5l0VaZ/K4sP7d5qASXW77KkukVJ9k/img.png&quot; data-alt=&quot;Segmentation을 사용한 주소 변환&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwzOYR/btqBp5l0VaZ/K4sP7d5qASXW77KkukVJ9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwzOYR%2FbtqBp5l0VaZ%2FK4sP7d5qASXW77KkukVJ9k%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;461&quot; width=&quot;542&quot; height=&quot;380&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Segmentation을 사용한 주소 변환&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;CPU는 &lt;b&gt;논리적 주소&lt;/b&gt;인 s와 d를 생성하는데, s는 segment id, d는 offset을 의미한다. &lt;b&gt;세그먼트는 세그먼트 테이블을 통해 실제 물리 메모리의 주소로 매핑된다&lt;/b&gt;.&lt;/p&gt;</description>
      <category>컴퓨터공학/운영체제</category>
      <category>50-percent rule</category>
      <category>compaction</category>
      <category>fragmentation</category>
      <category>Hashed Page Table</category>
      <category>Hierarchical Paging</category>
      <category>Inverted Page Table</category>
      <category>PAGING</category>
      <category>Segmentation</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/67</guid>
      <comments>https://empty-cloud.tistory.com/67#entry67comment</comments>
      <pubDate>Fri, 24 Jan 2020 02:17:21 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17825번] 주사위 윷놀이</title>
      <link>https://empty-cloud.tistory.com/66</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17825&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LgecV/btqBrAyivGx/pckqYyuA5yk1EHh2cKjJQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LgecV/btqBrAyivGx/pckqYyuA5yk1EHh2cKjJQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LgecV/btqBrAyivGx/pckqYyuA5yk1EHh2cKjJQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLgecV%2FbtqBrAyivGx%2FpckqYyuA5yk1EHh2cKjJQ1%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;74&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more66_0&quot; data-id=&quot;66_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content66_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less66_0&quot; data-id=&quot;66_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;브루트 포스&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이 문제는 2019년 삼성 하반기 SW 역량 테스트에서 나온 두 번째 문제이다.&lt;/p&gt;
&lt;p&gt;문제를 푸는데 3일이나 걸렸다... (도움을 주신 정인준 선배님 감사합니다ㅠㅠ)&lt;/p&gt;
&lt;p&gt;지금 와서 되돌아보니 풀이의 큰 흐름은 맞았지만, 문제에서 간과하기 쉬운 조건들이 있었다.&lt;/p&gt;
&lt;p&gt;이제는 삼성 SW 역량 테스트에서 알고리즘의 구현을 할 수 있는지 묻는 게 아니라, &lt;b&gt;문제 속에 찾기 힘든 조건들을 포함시키는 게 요즘 추세인 것 같다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;먼저, 백준에 나와있는 윷놀이 판의 그림은 헷갈리는 부분이 있으므로 이를 명확하게 하기 위해서 다음의 그림을 참고하면 좋을 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ntaki/btqBr8O4KOK/vsSbJBqix0KPntsiWRVJG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ntaki/btqBr8O4KOK/vsSbJBqix0KPntsiWRVJG0/img.png&quot; data-alt=&quot;윷놀이 판&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ntaki/btqBr8O4KOK/vsSbJBqix0KPntsiWRVJG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fntaki%2FbtqBr8O4KOK%2FvsSbJBqix0KPntsiWRVJG0%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; height=&quot;460&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윷놀이 판&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위와 같은 윷놀이 판에서, 모든 경우의 수를 따져야 하므로 말이 지나갈 경로를 정해야 한다. 경로를 어떻게 구성하고 구현할지는 사람마다 다르겠지만, 나는 다음과 같이 구현하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cW14aT/btqBr8IktcV/JQdM1EwLfkHluI4k5hU61K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cW14aT/btqBr8IktcV/JQdM1EwLfkHluI4k5hU61K/img.png&quot; data-alt=&quot;0번 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cW14aT/btqBr8IktcV/JQdM1EwLfkHluI4k5hU61K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcW14aT%2FbtqBr8IktcV%2FJQdM1EwLfkHluI4k5hU61K%2Fimg.png&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;0번 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dadLih/btqBpPX0IIB/W1RIwWikwPcMXdrblazZo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dadLih/btqBpPX0IIB/W1RIwWikwPcMXdrblazZo1/img.png&quot; data-alt=&quot;1번 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dadLih/btqBpPX0IIB/W1RIwWikwPcMXdrblazZo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdadLih%2FbtqBpPX0IIB%2FW1RIwWikwPcMXdrblazZo1%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1번 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0ZCsn/btqBqn7xfBl/wzkJNMkplXTZXY6a7LeXPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0ZCsn/btqBqn7xfBl/wzkJNMkplXTZXY6a7LeXPk/img.png&quot; data-alt=&quot;2번 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0ZCsn/btqBqn7xfBl/wzkJNMkplXTZXY6a7LeXPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0ZCsn%2FbtqBqn7xfBl%2FwzkJNMkplXTZXY6a7LeXPk%2Fimg.png&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2번 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bE9HpY/btqBqOX6KfI/1XhRYYa7dDst0uhCehSMok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bE9HpY/btqBqOX6KfI/1XhRYYa7dDst0uhCehSMok/img.png&quot; data-alt=&quot;3번 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bE9HpY/btqBqOX6KfI/1XhRYYa7dDst0uhCehSMok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbE9HpY%2FbtqBqOX6KfI%2F1XhRYYa7dDst0uhCehSMok%2Fimg.png&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3번 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp9F8U/btqBqpjWXCS/phSjOoVKcKFXb9yxI9tp8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp9F8U/btqBqpjWXCS/phSjOoVKcKFXb9yxI9tp8k/img.png&quot; data-alt=&quot;4번 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp9F8U/btqBqpjWXCS/phSjOoVKcKFXb9yxI9tp8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp9F8U%2FbtqBqpjWXCS%2FphSjOoVKcKFXb9yxI9tp8k%2Fimg.png&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1330&quot; width=&quot;650&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;4번 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이와 같은 경로는 코드의 4~10번째 줄에 선언되어 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;나는 브루트 포스를 DFS로 구현하였는데, 문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 턴마다 말이 움직일 횟수를 가져온다. (24~25번째 줄)&lt;/li&gt;
&lt;li&gt;현재 위치를 구하고, 만약 현재 위치가 도착지점이라면 다음 말로 넘어간다.(= 다음 말을 이동시킨다.) (32~34번째 줄)&lt;/li&gt;
&lt;li&gt;각 말마다 다음 위치를 구하고, 그다음 위치가 만약 각 코너와 중앙이라면, 이동할 경로의 번호와 위치를 바꿔준다. (36~56번째 줄)&lt;/li&gt;
&lt;li&gt;만약 말의 다음 위치가 도착을 넘어간다면, 도착에서 이동을 마친다. (58~60번째 줄)&lt;/li&gt;
&lt;li&gt;시작과 도착을 제외하고, 만약 현재 말의 다음 위치에 이미 다른 말이 있다면, 다음 말로 넘어간다.(= 다음 말을 이동시킨다.) (62~66번째 줄)&lt;/li&gt;
&lt;li&gt;모든 조건을 통과하고 난 후, 말을 이동시킨다. (68~71번째 줄)&lt;/li&gt;
&lt;li&gt;DFS를 통해 모든 경우를 재귀적으로 탐색한다. (73번째 줄)&lt;/li&gt;
&lt;li&gt;이동시킨 말을 다시 원래 위치로 되돌린다. (75~78번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3번 과정에서 내가 빠트렸던 점은, 0번 경로에서 40번 위치로 이동할 때, 4번 경로의 40번으로 위치 변경을 시켜주지 않았던 것이다.&lt;/p&gt;
&lt;p&gt;따라서 5번 과정에서, 실질적으로 0번 경로의 40번과 4번 경로의 40번은 같은 위치지만, 다른 위치로 판단하여 같은 위치에 말이 2개 있을 수 있었다.&lt;/p&gt;
&lt;p&gt;이 문제에서 신경 써야 할 점은 DFS로 브루트 포스를 구현하는 것이 아니라, 말 그대로 윷놀이 게임을 어떻게 구현할지 그 조건을 잘 찾아내는 게 중요한 것 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;예제 입력으로도 찾기 힘든 반례가 있다면 다음을 참고하면 좋을 것 같다.&lt;/p&gt;
&lt;p&gt;Input:&lt;/p&gt;
&lt;pre class=&quot;plaintext basic&quot;&gt;&lt;code&gt;3 5 2 5 3 5 2 1 3 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class=&quot;plaintext lsl&quot;&gt;&lt;code&gt;246&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다음의 말들을 순서대로 움직이면 위의 결과를 얻을 수 있다.&lt;/p&gt;
&lt;pre class=&quot;plaintext basic&quot;&gt;&lt;code&gt;1 2 2 1 1 1 1 1 2 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less66_0&quot; data-id=&quot;66_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more66_1&quot; data-id=&quot;66_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content66_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less66_1&quot; data-id=&quot;66_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import sys

movements = list(map(int, sys.stdin.readline().split()))
path_info = [
	[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0],
	[10, 13, 16, 19, 25],
	[20, 22, 24, 25],
	[30, 28, 27, 26, 25],
	[25, 30, 35, 40, 0]
]
# [i-th path, j-th block]
piece_positions = [[0, 0], [0, 0], [0, 0], [0, 0]]
piece_scores = [0, 0, 0, 0]
answer = 0


def dfs(idx):
	# termination condition
	if idx == 10:
		global answer
		answer = max(answer, sum(piece_scores))
		return answer
	
	# how many steps are going to be moved
	move = movements[idx]
	
	for i in range(4):
		# current piece position
		cur_path = piece_positions[i][0]
		cur_block = piece_positions[i][1]
		
		# if current piece finished the game
		if cur_block == len(path_info[cur_path]) - 1:
			continue
		
		next_path = cur_path
		next_block = cur_block + move
		# change path at the corner
		if cur_path == 0:
			if next_block == 5:
				next_path = 1
				next_block = 0
			elif next_block == 10:
				next_path = 2
				next_block = 0
			elif next_block == 15:
				next_path = 3
				next_block = 0
			elif next_block == 20:
				next_path = 4
				next_block = 3
		# change path at the center point
		elif cur_path &amp;lt; 4:
			if next_block &amp;gt;= len(path_info[cur_path]) - 1:
				next_path = 4
				next_block -= len(path_info[cur_path]) - 1
		
		# limit block to the last block of the path
		if next_block &amp;gt;= len(path_info[next_path]):
			next_block = len(path_info[next_path]) - 1
		
		# without the first &amp;amp; last block
		if path_info[next_path][next_block] != 0:
			# if next step is already taken
			if [next_path, next_block] in piece_positions:
				continue

		# move piece and update information
		piece_positions[i][0] = next_path
		piece_positions[i][1] = next_block
		piece_scores[i] += path_info[next_path][next_block]
		
		dfs(idx + 1)
		
		# reset piece and information
		piece_positions[i][0] = cur_path
		piece_positions[i][1] = cur_block
		piece_scores[i] -= path_info[next_path][next_block]


dfs(0)
print(answer)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less66_1&quot; data-id=&quot;66_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>브루트포스</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/66</guid>
      <comments>https://empty-cloud.tistory.com/66#entry66comment</comments>
      <pubDate>Thu, 23 Jan 2020 01:05:39 +0900</pubDate>
    </item>
    <item>
      <title>[운영체제] 메모리 관리 (1)</title>
      <link>https://empty-cloud.tistory.com/65</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Memory Access&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램은 실행되기 위해서 반드시 메모리에 로드되어야 한다.&lt;/li&gt;
&lt;li&gt;CPU는 오로지 레지스터와 메인 메모리에만 접근할 수 있다.&lt;/li&gt;
&lt;li&gt;메모리 유닛은 메모리 주소들의 흐름만 볼 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;context oblivious&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;메모리 주소만 알고 메모리에 대한 어떤 것도 모른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Memory Protection Mechanism&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cq4hl1/btqBoNRZmWd/oSJlUb1OqbIR0vuHE3sk10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cq4hl1/btqBoNRZmWd/oSJlUb1OqbIR0vuHE3sk10/img.png&quot; data-alt=&quot;Memory Protection Mechanism. Base register와 limit register의 값으로 메모리의 범위를 정한다. 메모리 주소는 다른 프로세스 영역에 접근하면 안된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cq4hl1/btqBoNRZmWd/oSJlUb1OqbIR0vuHE3sk10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcq4hl1%2FbtqBoNRZmWd%2FoSJlUb1OqbIR0vuHE3sk10%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;368&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Memory Protection Mechanism. Base register와 limit register의 값으로 메모리의 범위를 정한다. 메모리 주소는 다른 프로세스 영역에 접근하면 안된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Address Binding&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현대의 운영체제는 프로세스가 물리 메모리의 어떤 부분에도 상주할 수 있도록 한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;컴파일러는 &lt;span style=&quot;color: #006dd7;&quot;&gt;symbolic address&lt;/span&gt;를 &lt;span style=&quot;color: #006dd7;&quot;&gt;relocatable address(= relative address)&lt;/span&gt;로 &lt;b&gt;bind&lt;/b&gt; 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;링커와 로더는 &lt;span style=&quot;color: #006dd7;&quot;&gt;relocatable address&lt;/span&gt;를 &lt;span style=&quot;color: #006dd7;&quot;&gt;absolute address&lt;/span&gt;로 &lt;b&gt;bind&lt;/b&gt; 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Address Binding Time&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-filename=&quot;그림2.jpg&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;883&quot; width=&quot;324&quot; height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkCo2b/btqBpPPnenR/pGGbZzkNtdlMKs0yAP3mZk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkCo2b/btqBpPPnenR/pGGbZzkNtdlMKs0yAP3mZk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkCo2b/btqBpPPnenR/pGGbZzkNtdlMKs0yAP3mZk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkCo2b%2FbtqBpPPnenR%2FpGGbZzkNtdlMKs0yAP3mZk%2Fimg.jpg&quot; data-filename=&quot;그림2.jpg&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;883&quot; width=&quot;324&quot; height=&quot;535&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Compile time:&lt;/b&gt; 만약 메모리 주소가 연역적인 것으로 알려지면, absolute code가 생성된다; 메모리 주소의 변경이 일어나면 반드시 코드를 다시 컴파일해야 한다. 현재는 거의 쓰이지 않는다.&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Load time:&lt;/b&gt; 메모리 주소가 compile time에 알려지지 않았으면 반드시 relocatable code를 생성해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Execution time:&lt;/b&gt; 만약 프로세스가 실행되는 동안 한 개의 메모리 구역에서 다른 구역으로 옮겨갈 수 있다면, 바인딩은 런타임까지 늦춰진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Logical vs. Physical Address Space&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Physical address는 메모리 유닛에게 보여진다.&lt;/li&gt;
&lt;li&gt;Logical address는 CPU에 의해서 생성된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;compile time&lt;/span&gt;과 &lt;span style=&quot;color: #006dd7;&quot;&gt;load time&lt;/span&gt; 바인딩 시에는 physical address와 logical address는 같은 주소를 가리킨다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;항상 같은 Physical address를 바인딩한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Execution time&lt;/span&gt; 바인딩 시에는 다르다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Memory Management Unit (MMU)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;Virtual address를 Physical Address로 매핑하는 하드웨어 장치&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;1102&quot; data-origin-height=&quot;414&quot; width=&quot;543&quot; height=&quot;204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdDt9L/btqBn8oRoru/nUSwkK6kcLQ4vR1OS0nSD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdDt9L/btqBn8oRoru/nUSwkK6kcLQ4vR1OS0nSD1/img.png&quot; data-alt=&quot;Relocation register를 가지고 있는 간단한 MMU&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdDt9L/btqBn8oRoru/nUSwkK6kcLQ4vR1OS0nSD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdDt9L%2FbtqBn8oRoru%2FnUSwkK6kcLQ4vR1OS0nSD1%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;1102&quot; data-origin-height=&quot;414&quot; width=&quot;543&quot; height=&quot;204&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Relocation register를 가지고 있는 간단한 MMU&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;프로그램은 절대로 physical address를 볼 수 없다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span&gt;프로그램은 오로지 logical address 관점에서만 동작한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최종 physical address는 메모리에 접근될 때만 결정된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;c cpp&quot;&gt;&lt;code&gt;int a[10];
int *b;
b = a;
b = b + 4;
b = &amp;amp;b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 예에서, 5번째 줄에서 referencing을 할 때 메모리의 물리적 주소가 결정된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dynamic Linking&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;b&gt;Dynamic Linking:&lt;/b&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;Execution time&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;에 object 모듈을 연결하는 것&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static vs. dynamic linking
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;Static linking:&lt;/b&gt; 로더에 의해서 시스템 라이브러리들이 바이너리 프로그램으로 결합된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dynamic Linking:&lt;/b&gt; Linking이 execution time까지 미뤄진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dynamic Linking&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;프로그램 내에서 라이브러리를 호출하는 곳마다 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;stub&lt;/b&gt;&lt;/span&gt;이라는 작은 코드 조각이 생성된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;stub&lt;/b&gt;&lt;/span&gt;은 메모리 주소를 찾는 방법 또는 라이브러리를 메모리에 적재하는 법을 알고 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;라이브러리 버전을 업데이트할 때, static linking과 다르게 모든 프로그램을 재 컴파일할 필요가 없다.&lt;/li&gt;
&lt;li&gt;운영체제의 도움이 필요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;1080&quot; width=&quot;313&quot; height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yt0HO/btqBlA0wUU7/isFCsB0qjSMs8C6wMPx1Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yt0HO/btqBlA0wUU7/isFCsB0qjSMs8C6wMPx1Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yt0HO/btqBlA0wUU7/isFCsB0qjSMs8C6wMPx1Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyt0HO%2FbtqBlA0wUU7%2FisFCsB0qjSMs8C6wMPx1Uk%2Fimg.png&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;1080&quot; width=&quot;313&quot; height=&quot;419&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Dynamic Linking을 사용하는 이유: 라이브러리 전체를 메모리에 복사하는 것보다는 프로그램 간의 중복된 라이브러리를 줄이기 위해&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Swapping&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;프로세스를 실행하기 위해 필요한 메모리 공간이 물리 메모리의 용량을 넘어섰을 경우, &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;swapping&lt;/b&gt;&lt;/span&gt;을 사용할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Swapping&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;메모리의 프로세스를 일시적으로 디스크로 옮기거나, 디스크로부터 읽어오는 기술 (예: Round-Robin CPU 스케줄러)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림5.jpg&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;375&quot; width=&quot;427&quot; height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzrNdf/btqBpPWhooU/CN66utxdVKUFFKLfPSjM0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzrNdf/btqBpPWhooU/CN66utxdVKUFFKLfPSjM0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzrNdf/btqBpPWhooU/CN66utxdVKUFFKLfPSjM0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzrNdf%2FbtqBpPWhooU%2FCN66utxdVKUFFKLfPSjM0k%2Fimg.jpg&quot; data-filename=&quot;그림5.jpg&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;375&quot; width=&quot;427&quot; height=&quot;284&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Contiguous Memory Allocation (연속 메모리 할당)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Multiple partition allocation&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Fixed-sized partitions:&lt;/b&gt; batch 환경에서 주로 사용됨. 한 개의 파티션에 한 개의 프로세스가 위치한다. 더 이상 사용되지 않는 방법이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Variable partition size:&lt;/b&gt; 메모리의 어떤 부분이 사용 가능/불가능 한 지 나타내는 테이블을 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Hole:&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;사용 가능한 메모리 블록, 메모리 전체에 걸쳐서 흩어져있다.&lt;/span&gt; 프로세스가 메모리에 도착하면, 운영체제는 프로세스를 실행하기 위해 충분히 큰 블록을 찾는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사이즈 n의 요청을 어떻게 만족하지?
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;First Fit:&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;프로세스를 실행하기 위해 충분히 큰 hole 중, 가장 첫 번째 hole을 할당시킨다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Best Fit:&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;프로세스를 실행하기 위해 충분히 큰 hole 중, 가장 작은 hole을 할당시킨다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Worst Fit:&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;가장 큰 hole을 할당시킨다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;보통 &lt;span style=&quot;color: #006dd7;&quot;&gt;first fit&lt;/span&gt;과 &lt;span style=&quot;color: #006dd7;&quot;&gt;best fit&lt;/span&gt;이 &lt;span style=&quot;color: #006dd7;&quot;&gt;worst fit&lt;/span&gt;보다 더 나은 성능을 가진다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>컴퓨터공학/운영체제</category>
      <category>Address Binding</category>
      <category>Best Fit</category>
      <category>dynamic linking</category>
      <category>First Fit</category>
      <category>memory</category>
      <category>memory management unit</category>
      <category>stub</category>
      <category>Swapping</category>
      <category>Worst Fit</category>
      <category>운영체제</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/65</guid>
      <comments>https://empty-cloud.tistory.com/65#entry65comment</comments>
      <pubDate>Tue, 21 Jan 2020 15:54:03 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 5] Gerrit 사용하기 (2)</title>
      <link>https://empty-cloud.tistory.com/64</link>
      <description>&lt;p&gt;이번 포스트에서는, 변경 사항에 대해서 어떻게 추적하고, 각 리뷰 점수가 어떤 의미를 갖는지 알아보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;변경사항 추적하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;변경사항을 제출하고 난 후, &lt;a href=&quot;https://review.opendev.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;서 변경사항을 추적할 수 있습니다. 로그인 후, 제출한 변경사항에 대해서 &quot;Outgoing reviews&quot;, 리뷰하고 있는 변경사항에 대해서 &quot;Incoming reviews&quot;, 본인이 리뷰어이거나 소유자인 변경사항에 대해 &quot;Recently closed&quot;인 대시보드를 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;리뷰어 추가하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;때로는 우리의 패치에 대해서 의견을 내줄 사람들이 필요할 때가 있습니다. 왜냐하면 그 사람들은 여러 권한을 가지고 있을 수도 있고, 당신을 돕는 멘토일 수도 있기 때문입니다. 우리가 새로운 패치나 패치셋을 업로드했다는 것을 알리는 가장 쉬운 방법은 gerrit 웹 UI에서 그 사람들을 리뷰어로 추가하는 것입니다. 우리는 이름, gerrit 이메일 주소, ssh 사용자 이름 또는 gerrit ID로 검색할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duCDM4/btqBkOXVLbL/Z9tol21HVKIgosoLjh6yR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duCDM4/btqBkOXVLbL/Z9tol21HVKIgosoLjh6yR1/img.png&quot; data-alt=&quot;리뷰어를 명시적으로 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duCDM4/btqBkOXVLbL/Z9tol21HVKIgosoLjh6yR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduCDM4%2FbtqBkOXVLbL%2FZ9tol21HVKIgosoLjh6yR1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리뷰어를 명시적으로 추가하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;일반적으로 패치마다 각 상호작용(새로운 패치셋, 코멘트, CI 시스템 투표 등)이 해당 패치에 대한 모든 리뷰어들에게 이메일 알림을 보낼 것이기 때문에 이 기능을 과도하게 사용하지 않는 것이 좋습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;만약 우리가 패치에 대해서 리뷰한다면 자동으로 리뷰어 목록에 추가됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Gerrit 웹 에디터&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;우리는 로컬에서 변경하지 않고 Gerrit 웹 인터페이스에서 패치를 편집하고 변경 내용을 게시할 수 있습니다. 작업하고 있는 로컬 브랜치가 자동으로 업데이트되지 않으므로, 양이 많은 코드 업데이트에는 일반적으로 권장되지 않습니다. 패치가 기본적으로 작은 pep8 failure(whitespace at the end of line, needing to wrap a line 등)을 제외하고 병합할 준비가 돼있는 몇몇 경우에, 이 gerrit 기능은 'git add', 'git commit --amend', 'git review' 과정을 거치지 않고 변경사항을 수정하고 게시하는데 매우 편리할 수 있습니다.&lt;/p&gt;
&lt;p&gt;Gerrit 웹 에디터에 접근하기 위해, 파일의 Gerrit Code Review 페이지의 상단에 있는 패치셋 숫자 옆에 있는 종이 위에 글을 쓰고 있는 연필 같이 생긴 아이콘을 클릭하세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgNVR9/btqBn8ulHO9/zEoi7ab8RKtkWI3rfohs3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgNVR9/btqBn8ulHO9/zEoi7ab8RKtkWI3rfohs3k/img.png&quot; data-alt=&quot;웹 브라우저로부터 변경사항 수정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgNVR9/btqBn8ulHO9/zEoi7ab8RKtkWI3rfohs3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgNVR9%2FbtqBn8ulHO9%2FzEoi7ab8RKtkWI3rfohs3k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;웹 브라우저로부터 변경사항 수정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;변경사항 리뷰하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;거의 모든 레포지토리에서, Gerrit은 패치에 대해 5가지 투표 선택사항을 제공합니다. +2점과&amp;nbsp;-2점은 프로젝트의 핵심 리뷰 팀의 멤버들만 사용할 수 있습니다. 모두가 -1점과 +1점을 투표할 수 있습니다. 우리는 0점으로 아무 투표 없이 코멘트를 남길 수도 있습니다. 모든 경우에 우리는 최선의 판단을 하지만, 우리를 가이드하기 위해 커뮤니티의 경험으로부터 이러한 휴리스틱을 제공합니다.&lt;/p&gt;
&lt;p&gt;OpenStack을 발전시키는 것은 패치 커미터들입니다. &lt;b&gt;리뷰어로써, 우리가 커미터들에게 서비스를 제공한다는 것을 기억하세요. 그 반대가 아닙니다.&lt;/b&gt; 커미터로써, 모든 사람이 동일한 규칙을 적용받는다는 것을 기억하세요. 우리의 패치에 투표하는 핵심 리뷰어들도 그들의 검토사항에 대해 동일한 리뷰 과정을 거칩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code Review +2&lt;/h3&gt;
&lt;p&gt;+2점의 투표는 핵심 리뷰어들만 사용할 수 있습니다. 일부 프로젝트에서는 +2점 만을 요구하고, 많은 프로젝트에서는 특정 상황(사소한 변경 등)에서 요구사항을 완화하지만, &lt;b&gt;변경사항이 병합되기 전에 2개의 +2점을 요구하도록 권장됩니다&lt;/b&gt;. 만약 핵심 리뷰어인 경우, 로컬 정책을 확인하세요. 헷갈리지만, &lt;b&gt;2개의 +1점과 +2점은 같은 게 아닙니다!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;승인 없이 +2점을 투표하는 것은 다른 핵심 리뷰어가 변경사항을 승인하는 것에 만족한다는 것을 나타냅니다. 만약 다른 핵심 리뷰어가 이미 +2점을 투표했다면, 우리는 일반적으로 동시에 변경사항을 승인할 것입니다. 하지만 작성자나 다른 리뷰어가 적절하다고 생각될 경우, 사소한 피드백에 응답할 기회를 주기 위해 승인을 보류할 수 있습니다. 만약 피드백이 충분히 사소한 것이라면, +1점만 투표하는 것이 더 바람직합니다.&lt;/p&gt;
&lt;p&gt;만약 다른 핵심 리뷰어가 이전의 패치셋에서 +2점을 투표했고, 해당 패치 이후 리뷰어들이 충분히 만족할 것으로 확신할 수 있는 사소한 방식으로만 변경된 경우, 다시 검토하기를 기다리지 말고 +2점으로 승인하세요. 이렇게 할 때에는 왜 그런 결정을 내렸는지 설명하는 코멘트를 남기세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code Review +1&lt;/h3&gt;
&lt;p&gt;핵심 리뷰어가 아닌 경우, +1점은 변경사항을 검토했으며, 변경사항을 병합하는데 만족한다는 것을 나타냅니다. 우리의 기록이 핵심 리뷰 팀에게 알려지지 않는 경우, 코멘트 없이 +1점만 남기는 것은 그다지 유용하지 않습니다. (이 경우 곧 핵심 리뷰 팀에게 알려질 가능성이 큽니다.) 변경사항이 합당한 경우, 코멘트를 남기세요. 만약 패치를 테스트한 경우, 그렇게 말하세요: 올바른 패치인지 확인하기 위해 참조한 어떤 것이라도 있다면, 다음 리뷰어를 위해서 참조 링크와 함께 코멘트를 남기세요.&lt;/p&gt;
&lt;p&gt;핵심 리뷰어들도 +1점을 사용할 수 있습니다. 패치가 괜찮다고 생각하지만 열린 질문이 있거나, 후속 변경에서 고칠 수 있는 사소한 피드백이 있지만 그 기여자에게 변경사항을 스스로 고칠 수 있는 기회를 주고 싶을 때 +1점을 주는 것을 고려해보세요. 예를 들어, 리뷰어들도 우리의 의견을 원하거나 우리를 도와주고 싶어 하기 때문입니다. 만약 기여자가 멘토를 찾고 있는지, 아니면 패치를 수정하거나 후속 변경사항을 직접 제출하기를 원하는지 확실하지 않은 경우, 직접 물어보세요! 많은 기여자들이 핵심 리뷰어들의 +1점에 빠르게 응답할 것입니다. 왜냐하면 기여자들은 그것이 +2점에 거의 다 왔다는 것을 알고 있고, 이것이 기여자를 격려하고 호의를 베푸는 데 -1점보다 훨씬 낫기 때문입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;핵심 리뷰어들조차 프로젝트의 모든 부분에 익숙하지 않을 수 있습니다. 자신 없는 영역에서 변경사항이 생기면 +1점을 투표할 수 있고, 그렇지 않다면 +2점을 투표하면 됩니다. 항상 그렇듯이, 왜 그런지 말하는 코멘트를 남기는 것이 도움이 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code Review 0&lt;/h3&gt;
&lt;p&gt;만약 우리가 변경 사항에 대해서 어떤 쪽이든 강한 느낌을 가지고 있지 않거나, 의견을 결정하기 위해 대답해야 할 질문이 있다면, 리뷰 없이 코멘트를 남길 수 있습니다. 만약 우리가 질문에 대한 답이 문제를 드러낼 것이라고 확신이 안 든다면, 처음에 -1점을 투표하는 것이 낫습니다. -1점이 없는 코멘트는 실수로 놓치기 쉬우므로, 답변이 없는 채로 시간이 꽤 지났거나, 우리의 코멘트에 아무도 답변을 하지 않고 새 패치셋이 게시된 경우, IRC로 제출자에게 연락하거나 -1을 고려해봐야 할 때일 수도 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code Review -1&lt;/h3&gt;
&lt;p&gt;-1점을 사용해서 변경사항이 병합되기 전에 패치가 수정되어야 한다고 굳게 믿는 문제를 발견했다는 것을 알리세요. 변경사항에 의해 유발된 새로운 버그부터 커밋 메시지의 오타(만약 git 기록에서 &lt;span style=&quot;color: #333333;&quot;&gt;핵심 단어에 &lt;/span&gt;패치를 찾기 어렵게 만드는 오타가 있는 경우)처럼 사소한 것에 이르기까지 -1점을 주는 여러 가지 이유가 있습니다. 다시 한번, 최선의 판단을 하되, -1점을 투표할 때는 우리가 다른 사람의 일을 방해하는 것이므로 다른 방법(예: 후속 조치 변경)으로 해결할 수 없는 타당한 이유인지 확인하세요.&lt;/p&gt;
&lt;p&gt;많은 리뷰어들이 이미 부정적인 리뷰가 있는 변경사항에 대해 우선순위를 두지 않을 것이라는 것을 기억하세요. 따라서 -1점을 투표함으로써 제출자에게 다른 개선을 요구하는 것뿐만 아니라, 더 많은 피드백으로부터 -1점을 잠재적으로 차단할 수 있습니다.&lt;/p&gt;
&lt;p&gt;-1점의 리뷰에는 항상 실행 가능한 피드백이 포함된 코멘트가 동반되어야 합니다.&lt;/p&gt;
&lt;p&gt;만약 많은 수의 패치셋이 있는 변경사항에 대해 리뷰할 경우, 이상한 점이 보이는지 이전의 기록을 돌아보는 것을 잊지 마세요. 그게 이전의 리뷰어에 의해 요청되었을지도 모릅니다. 만약 우리가 핵심 리뷰어이고, 우리가 다른 핵심 리뷰어에 의해 주어진 조언에 반대되는 조언을 할 필요가 있다고 생각한다면, 다른 리뷰어와 합의에 도달하는 것이 우리의 책임이고, 둘 다 문서화하는 것이 이상적입니다. -1점을 투표하기 전에, 변경사항이 무언가 망가트리지 않는 이상(이 경우, 상충되는 의견이 있고, 그 문제를 가능한 한 빨리 해결하기 위해 작업 중이라는 것을 알리는 코멘트를 남기세요), 핵심 리뷰어들 간의 의견 불일치를 다루는 것은 패치 제출자의 책임이 아닙니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code Review -2&lt;/h3&gt;
&lt;p&gt;+2점의 투표는 핵심 리뷰어들만 사용할 수 있습니다. 다른 투표와 다르게, -2점은 'sticky'합니다. -2점은 제출자가 새로운 패치를 푸시해도 변경되지 않습니다. 즉, -2점을 지우려면 동일한 핵심 리뷰어의 조치가 필요하므로 주의하세요. -2점의 목적은 변경 제출자에게 그 변경 사항에 대해 작업하는 시간은 분명히 낭비될 것이라는 것을 알리는 것입니다. 만약 변경사항에 대해 -2점의 리뷰를 받는다고 기분 나쁘게 생각하지 마세요! 그 리뷰어는 우리의 소중한 시간과 에너지를 병합될 가능성이 있는 변화로 돌리려고 하는 것입니다.&lt;/p&gt;
&lt;p&gt;-2점의 리뷰는 항상 그 변경사항이 프로젝트의 목표에 부합하지 않는 이유를 설명하는 코멘트를 첨부해서, 제출자가 그 이유를 이해하고 추후의 기여에 대해서 더 생산적으로 집중할 수 있도록 해야 합니다.&lt;/p&gt;
&lt;p&gt;아래의 '&lt;b&gt;Procedural Code Review -2&lt;/b&gt;'를 제외하고, -2점의 적법한 용도는 없습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Procedural Code Review -2&lt;/h3&gt;
&lt;p&gt;일부 프로젝트에서는 Feature Freeze 후, 다음 릴리즈로 branching 하기 전에 Feature Freeze 동안 의도치 않게 기능이 병합되지 않도록 변경사항에 대해 -2점을 투표합니다. -2점을 투표한 사람은 마스터 브랜치가 새로운 기능을 위해 다시 열리면 -2점을 제거할 것입니다. -2점을 투표한 사람들은 무슨 일이 일어나고 있는지 설명하는 코멘트를 남겨야 합니다. 제출자들은 Freeze 기간 동안 변경 사항을 계속 수정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Workflow -1&lt;/h3&gt;
&lt;p&gt;Workflow -1점은 변경사항이 현재 전체적인 리뷰를 위한 준비가 되어있지 않음을 나타냅니다. &lt;b&gt;핵심 리뷰어와 변경 소유자만 Workflow -1점에 투표할 수 있습니다.&lt;/b&gt; 모든 Workflow 투표는 새 패치셋을 제출할 때마다 삭제됩니다. 이것은 (명시적으로 추가되지 않은 리뷰어들로부터 가려진) Draft 변경사항의 레거시 방법보다 진행 중인 작업에 대해 피드백을 얻는 더 나은 방법입니다.&lt;/p&gt;
&lt;p&gt;핵심 리뷰어들도 코드 리뷰 프로세스를 중단하지 않고 일시적인 조건 중 변경사항이 병합되는 것을 방지하기 위해 Workflow -1점에 투표할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Workflow +1&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Workflow +1점은 변경사항이 핵심 리뷰어로부터 승인될 때 사용됩니다.&lt;/b&gt; Workflow +1점 없이 아무리 2개의 Code Review +2점을 받았다고 하더라도 변경사항은 병합되지 않습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다른 변경사항 살펴보기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;Gerrit에서 다른 기여자의 패치를 확인하고 변경할 수 있지만, 작업하기 전에 항상 그 기여자와 변경사항에 대해 논의해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext armasm&quot;&gt;&lt;code&gt;git-review -d &amp;lt;change ID&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;change ID&amp;gt;는 Gerrit의 web UI에서 찾을 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/skj7v/btqBmVvjbsJ/uTUGmtLcng8YBLy0K4Wta0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/skj7v/btqBmVvjbsJ/uTUGmtLcng8YBLy0K4Wta0/img.png&quot; data-alt=&quot;변경사항의 change ID&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/skj7v/btqBmVvjbsJ/uTUGmtLcng8YBLy0K4Wta0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fskj7v%2FbtqBmVvjbsJ%2FuTUGmtLcng8YBLy0K4Wta0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변경사항의 change ID&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;패치에 대해 체크아웃한 후, 자동으로 새로운 브랜치로 변경될 것이고, 거기서 우리는 새로운 변경사항에 대해 작업할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cherry-picking&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;만약 우리의 커밋이 작업을 시작한 후 업데이트된 변경사항에 대해 의존적이고, 해당 변경사항으로부터 새로운 패치셋을 가져와야 할 경우, 우리의 변경사항 위로 cherry-pick을 할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext armasm&quot;&gt;&lt;code&gt;git-review -x &amp;lt;change ID&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;change ID&amp;gt;는 이전의 경우와 동일합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Merging&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;만약 변경사항이 승인되고 게이트 작업을 통과하면 Gerrit은 자동으로 최신 패치셋을 병합합니다.&lt;/p&gt;
&lt;p&gt;각 패치셋은 테스트하기 전에 브랜치의 HEAD에 병합됩니다. Gerrit이 패치셋을 병합할 수 없는 경우, -1점 리뷰를 주고 병합 실패에 대한 코멘트를 추가합니다.&lt;/p&gt;
&lt;p&gt;변경사항이 병합될 때마다, &quot;merge-check&quot; 파이프라인은 동일한 프로젝트에 열려있는 모든 변경사항이 여전히 병합 가능한지 검증합니다. 만약 어떤 작업이든 병합할 수 없다면, Zuul은 -1점의 리뷰를 주고, 병합 실패에 대한 코멘트를 추가합니다.&lt;/p&gt;
&lt;p&gt;변경사항이 병합된 후에는, 프로젝트별로 사후 작업이 실행됩니다. 대부분의 post 작업은 문서를 게시하거나, coverage를 실행하거나, 번역 서버에 문자열을 전송합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Project Gating&lt;/h3&gt;
&lt;p&gt;프로젝트 게이팅은 개발자의 패치셋이 병합되기 전에 회귀 테스트(regression test)를 실행하는 과정을 말합니다. 회귀 테스트를 실행하는 목적은 소스 코드 저장소에 제출된 새로운 변경사항이 새로운 버그를 유발하지 않는지 검증하는 것입니다. 게이팅은 일련의 테스트가 성공적으로 통과된 후에 패치셋이 개발의 주류로 병합되도록 함으로써 퇴보를 방지합니다.&lt;/p&gt;
&lt;p&gt;게이팅에 사용되는 시스템은 Zuul로, Gerrit 이벤트 스트림을 listen 하고 YAML 파일로 구성하여 이벤트에 응답하여 실행할 일련의 테스트를 정의합니다.&lt;/p&gt;
&lt;p&gt;대기열의 작업은 핵심 리뷰어가 변경사항을 승인하고(+1 Workflow를 사용하여) verified 된 +1점 투표가 존재하면 실행됩니다. 승인 시 최소 1개의 +2점 코드 리뷰 투표가 존재해야 합니다. (핵심 리뷰어가 승인할 때 부여할 수 있습니다.) &lt;b&gt;즉, 이 컨벤션은 승인을 위해 2개의 +2점 코드 리뷰가 필요하다는 것입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;구성된 게이트 파이프라인에서 승인된 패치셋에 대해&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;모든 작업이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;성공하면, Gerrit은 trunk로 코드를 병합할 것입니다.&lt;/p&gt;
&lt;p&gt;게이트 테스트를 실행하는 것 외에도, 게이트 파이프라인은 여러 프로젝트들에 대해서 병합하기 위한 변경사항들의 순서를 결정합니다. 변경사항들은 이 순서에 따라 테스트되고 병합되므로, 각 변경사항에 대해 다른 모든 레포지토리의 상태를 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zuul.openstack.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;서 각 작업들의 상태를 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbgRhc/btqBn8VMcMU/wsbPbpZBkQl7D9ku6bXLR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbgRhc/btqBn8VMcMU/wsbPbpZBkQl7D9ku6bXLR0/img.png&quot; data-alt=&quot;https://zuul.openstack.org/에 접속하면 볼 수 있는 화면. 현재 zuul에서 동작하고있는 모든 작업들의 상태를 나타낸다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbgRhc/btqBn8VMcMU/wsbPbpZBkQl7D9ku6bXLR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbgRhc%2FbtqBn8VMcMU%2FwsbPbpZBkQl7D9ku6bXLR0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://zuul.openstack.org/에 접속하면 볼 수 있는 화면. 현재 zuul에서 동작하고있는 모든 작업들의 상태를 나타낸다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/contributors/code-and-documentation/using-gerrit.html&quot;&gt;https://docs.openstack.org/contributors/code-and-documentation/using-gerrit.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/project-team-guide/review-the-openstack-way.html&quot;&gt;https://docs.openstack.org/project-team-guide/review-the-openstack-way.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/infra/manual/developers.html#code-review&quot;&gt;https://docs.openstack.org/infra/manual/developers.html#code-review&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>gerrit</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/64</guid>
      <comments>https://empty-cloud.tistory.com/64#entry64comment</comments>
      <pubDate>Mon, 20 Jan 2020 12:00:01 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17822번] 원판 돌리기</title>
      <link>https://empty-cloud.tistory.com/63</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17822&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgy9rB/btqBh1owNYd/XKKmu2DscWVRjPtXaEUuLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgy9rB/btqBh1owNYd/XKKmu2DscWVRjPtXaEUuLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgy9rB/btqBh1owNYd/XKKmu2DscWVRjPtXaEUuLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcgy9rB%2FbtqBh1owNYd%2FXKKmu2DscWVRjPtXaEUuLk%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more63_0&quot; data-id=&quot;63_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content63_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less63_0&quot; data-id=&quot;63_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;BFS&lt;/b&gt;와 &lt;b&gt;시뮬레이션&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;갈수록 삼성 SW 역량 테스트의 문제가 점점 더 구현에 까다로운 조건을 추가하기 시작하는 게 느껴진다.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;먼저, 문제를 풀기 위해 &lt;span style=&quot;color: #333333;&quot;&gt;원판의 숫자를 어떻게 표현할 것인지에 &lt;/span&gt;대해서 생각해보아야 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제에서 주어진 원판을 행렬로 표현하면 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UYXE0/btqBg9tQKd1/xWqmtNjnZ8IUAZBypkYSTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UYXE0/btqBg9tQKd1/xWqmtNjnZ8IUAZBypkYSTk/img.png&quot; data-alt=&quot;원판을 행렬로 나타낸 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UYXE0/btqBg9tQKd1/xWqmtNjnZ8IUAZBypkYSTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUYXE0%2FbtqBg9tQKd1%2FxWqmtNjnZ8IUAZBypkYSTk%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;604&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원판을 행렬로 나타낸 그림&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이제 원판을 행렬로 나타냈으니, 원판을 회전시키는 함수를 작성한다.&lt;/p&gt;
&lt;p&gt;i번째의 원판을 회전시킬 때, i의 배수인 원판 모두 회전을 시켜야 한다.&lt;/p&gt;
&lt;p&gt;이 부분에 대한 구현은 13~27번째 줄에 다음과 같이 구현되어 있다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def rotate(_x, _d, _k):
	# rotate counter-clockwise
	if _d:
		# for all disks which is multiple of x
		for i in range(_x, n + 1, _x):
			temp = deque(disk[i][1:])
			temp.rotate(-(_k % m))
			disk[i][1:] = temp
	# rotate clockwise
	else:
		# for all disks which is multiple of x
		for i in range(_x, n + 1, _x):
			temp = deque(disk[i][1:])
			temp.rotate(_k % m)
			disk[i][1:] = temp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;deque 자료형은 built-in 함수로 rotate 함수를 제공한다.&lt;/p&gt;
&lt;p&gt;그래서 나는 주어진 원판의 행렬에서 각 행을 deque 자료형으로 바꾸고, 회전시켜주었다.&lt;/p&gt;
&lt;p&gt;지금 생각해보니 list형이 아니라 deque형으로 원판의 숫자를 읽어도 될 것 같다.&lt;/p&gt;
&lt;p&gt;문제를 해결하기 위한 기본적인 함수를 작성했으니, 이제 문제에서 주어진대로 문제를 풀면 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;주어진 횟수만큼 문제에서 언급한 대로 원판을 회전시킨다. (31~33번째 줄)&lt;/li&gt;
&lt;li&gt;원판을 회전시킨 후, 모든 칸에 대한 BFS를 통해 인접하면서 같은 숫자를 찾는다. (35~63번째 줄, 70번째 줄)&lt;/li&gt;
&lt;li&gt;BFS를 통해 찾은 인접한 숫자 중 같은 숫자가 있다면 그 숫자들을 원판에서 지운다. (65~68번째 줄)&lt;/li&gt;
&lt;li&gt;BFS를 통해 찾은 인접한 숫자 중 같은 숫자가 없다면, 원판에 적힌 숫자들의 평균을 구하고, 평균보다 큰 수에서 1을 빼고 평균보다 작은 수에는 1을 더한다. (72~90번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 문제가 까다로운 점은 숨은 조건이 있다는 것이다.&lt;/p&gt;
&lt;p&gt;먼저 첫 번째 숨은 조건은 2번에 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;우리는 먼저 원판을 행렬로 표현했다. 하지만 여기서 주의할 점은, &lt;b&gt;원판에서 인접한 숫자는 행렬의 양쪽 끝도 인접해있다는 것이다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;다음의 그림을 보면 이해하기 쉽다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6UGAq/btqBh0QJAP3/JedxjE4TWpjDgkrwGANWyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6UGAq/btqBh0QJAP3/JedxjE4TWpjDgkrwGANWyK/img.png&quot; data-alt=&quot;원판에서 인접한 숫자를 찾기 위한 숨은 조건&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6UGAq/btqBh0QJAP3/JedxjE4TWpjDgkrwGANWyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6UGAq%2FbtqBh0QJAP3%2FJedxjE4TWpjDgkrwGANWyK%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;604&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원판에서 인접한 숫자를 찾기 위한 숨은 조건&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;따라서 BFS를 통해 인접하면서 같은 숫자를 찾기 위해서는 이 숨은 조건 또한 포함해야 한다.&lt;/p&gt;
&lt;p&gt;이 숨은 조건은 56~63번째 줄에 구현되어 있다.&lt;/p&gt;
&lt;p&gt;사실 이 조건은 이미 문제에 제시되어 있지만, 간과하기 쉬운 조건이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;300&quot; width=&quot;364&quot; height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnQqBs/btqBgDPxaBU/jHaRDkdSRkWK7DJFiST3pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnQqBs/btqBgDPxaBU/jHaRDkdSRkWK7DJFiST3pk/img.png&quot; data-alt=&quot;문제에 제시돼있는 인접한 수의 조건&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnQqBs/btqBgDPxaBU/jHaRDkdSRkWK7DJFiST3pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnQqBs%2FbtqBgDPxaBU%2FjHaRDkdSRkWK7DJFiST3pk%2Fimg.png&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;300&quot; width=&quot;364&quot; height=&quot;178&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;문제에 제시돼있는 인접한 수의 조건&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;두 번째 숨은 조건은 원판에 적힌 숫자들의 평균을 구할 때이다.&lt;/p&gt;
&lt;p&gt;백준의 예제 입력에서는 찾을 수 없는 조건이지만, 19년 하반기 삼성전자 SW 역량 테스트의 예제 입력에서 찾을 수 있는 조건이었다.&lt;/p&gt;
&lt;p&gt;원판에서 평균을 구할 때 0이 아닌 숫자를 찾아야 하는데, &lt;b&gt;이때 0이 아닌 숫자가 없다면 division by zero 에러가 발생한다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;따라서 이 부분에 대해서도 조건 검사를 해주어야 한다.&lt;/p&gt;
&lt;p&gt;이 숨은 조건은 80~82번째 줄에 구현되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less63_0&quot; data-id=&quot;63_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more63_1&quot; data-id=&quot;63_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content63_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less63_1&quot; data-id=&quot;63_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import sys
from collections import deque

# initialize
n, m, t = map(int, sys.stdin.readline().split())
disk = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
for r in range(1, n + 1):
	line = list(map(int, sys.stdin.readline().split()))
	for c in range(1, m + 1):
		disk[r][c] = line[c - 1]


def rotate(_x, _d, _k):
	# rotate counter-clockwise
	if _d:
		# for all disks which is multiple of x
		for i in range(_x, n + 1, _x):
			temp = deque(disk[i][1:])
			temp.rotate(-(_k % m))
			disk[i][1:] = temp
	# rotate clockwise
	else:
		# for all disks which is multiple of x
		for i in range(_x, n + 1, _x):
			temp = deque(disk[i][1:])
			temp.rotate(_k % m)
			disk[i][1:] = temp


directions = ((0, 1), (1, 0), (0, -1), (-1, 0))
for _ in range(t):
	x, d, k = map(int, sys.stdin.readline().split())
	rotate(x, d, k)
	
	found = False
	total_visited = set()
	for r in range(1, n + 1):
		for c in range(1, m + 1):
			if (r, c) not in total_visited:
				q = deque([(r, c)])
				visited = set([(r, c)])
				
				# BFS
				while q:
					cur_r, cur_c = q.pop()
					
					# for 4 adjacent numbers
					for dr, dc in directions:
						next_r = cur_r + dr
						next_c = cur_c + dc
						if 0 &amp;lt; next_r &amp;lt;= n and 0 &amp;lt; next_c &amp;lt;= m and (next_r, next_c) not in visited:
							# if it's the same number
							if disk[next_r][next_c] and disk[cur_r][cur_c] == disk[next_r][next_c]:
								q.appendleft((next_r, next_c))
								visited.add((next_r, next_c))
					# hidden condition for circular disk
					if disk[cur_r][cur_c]:
						if (cur_r, m) not in visited and cur_c == 1 and disk[cur_r][cur_c] == disk[cur_r][m]:
							q.appendleft((cur_r, m))
							visited.add((cur_r, m))
						elif (cur_r, 1) not in visited and cur_c == m and disk[cur_r][cur_c] == disk[cur_r][1]:
							q.appendleft((cur_r, 1))
							visited.add((cur_r, 1))
				
				if len(visited) &amp;gt; 1:
					for vr, vc in visited:
						disk[vr][vc] = 0
					found = True
				
				total_visited |= visited
					
	if not found:
		count, average = 0, 0
		for i in range(1, n + 1):
			for j in range(1, m + 1):
				if disk[i][j]:
					count += 1
					average += disk[i][j]
		
		# filter divide by zero
		if count:
			average /= count

		for i in range(1, n + 1):
			for j in range(1, m + 1):
				if disk[i][j]:
					if disk[i][j] &amp;gt; average:
						disk[i][j] -= 1
					elif disk[i][j] &amp;lt; average:
						disk[i][j] += 1
	
print(sum(map(sum, disk)))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less63_1&quot; data-id=&quot;63_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>bfs</category>
      <category>백준</category>
      <category>시뮬레이션</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/63</guid>
      <comments>https://empty-cloud.tistory.com/63#entry63comment</comments>
      <pubDate>Thu, 16 Jan 2020 15:22:15 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17837번] 새로운 게임 2</title>
      <link>https://empty-cloud.tistory.com/62</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17837&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l4pAx/btqBdTEE9bX/Y8YqVeJML5rWbxHP3iLFUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l4pAx/btqBdTEE9bX/Y8YqVeJML5rWbxHP3iLFUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l4pAx/btqBdTEE9bX/Y8YqVeJML5rWbxHP3iLFUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl4pAx%2FbtqBdTEE9bX%2FY8YqVeJML5rWbxHP3iLFUK%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;72&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more62_0&quot; data-id=&quot;62_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content62_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less62_0&quot; data-id=&quot;62_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;이 문제는 알고리즘 분류는 되어있지 않지만, &lt;b&gt;시뮬레이션&lt;/b&gt; 문제라고 생각한다.&lt;/p&gt;
&lt;p&gt;갈수록 삼성의 SW 역량 테스트가 점점 어려워지는 게 느껴진다.&lt;/p&gt;
&lt;p&gt;개인적으로 문제를 읽자마자 &lt;b&gt;스택/큐&lt;/b&gt;의 개념이 떠올랐지만, 막상 파이썬으로 구현하니 스택/큐를 쓸 일이 없었다.&lt;/p&gt;
&lt;p&gt;또한 C/C++의 포인터를 쓰고 싶었지만, 파이썬에는 포인터의 개념이 없기 때문에 해결법을 구상하는데 꽤나 오랜 시간이 걸렸다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 풀기 전, 중요한 변수가 3개 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;board_info:&lt;/b&gt; 체스판의 색깔 정보를 담고있는 변수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;board:&lt;/b&gt; 체스판 위의 체스말 정보를 담고 있는 변수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;chess_pieces:&lt;/b&gt; 체스말 리스트 (각 체스 말의 행, 열과 방향을 담고 있다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이를 가지고 문제를 해결하였다.&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;체스 말이 다음에 이동할 곳의 정보를 얻는다. (&lt;b&gt;만약 다음 칸이 체스판 바깥이거나 파란색이라면 방향만 바꿔준다.&lt;/b&gt;) (51~52번째 줄)&lt;/li&gt;
&lt;li&gt;만약 다음에 이동할 칸이 현재 위치와 같다면(= 다음 칸이 체스판 바깥이거나 파란색이라면) 다음 체스 말로 넘어간다. (체스 말의 방향은 1번에서 이미 바뀌었다.) (54~56번째 줄)&lt;/li&gt;
&lt;li&gt;현재 칸에서 이동할 말을 기준으로 현재 칸에 있는 체스 말들을 이등분한다. (58~60번째 줄)&lt;/li&gt;
&lt;li&gt;만약 다음에 이동할 칸이 흰색이라면 체스말들을 옮기고, 체스 말들의 위치를 업데이트한다.(= chess_pieces의 값을 업데이트한다.) (62~67번째 줄)&lt;/li&gt;
&lt;li&gt;만약 다음에 이동할 칸이 빨간색이라면 체스말들의 순서를 뒤집어서 옮기고, 체스말들의 위치를 업데이트한다. (68~73번째 줄)&lt;/li&gt;
&lt;li&gt;만약 체스 말을 옮긴 곳에 체스 말이 4개 이상이라면 현재 턴을 출력하고 종료한다.&lt;/li&gt;
&lt;li&gt;각 턴마다 모든 체스 말에 대해 위 작업을 반복하고, 턴이 1000 이상이면 -1을 출력한다. (48~50번째 줄, 79번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3번부터 5번의 과정을 그림으로 요약하자면 다음과 같다.&lt;/p&gt;
&lt;p&gt;체스판의 파란색 칸은 2번 과정을 실행하면서 자동으로 처리된다. (이는 코드의 흐름을 따라가다 보면 이해할 수 있다.)&lt;/p&gt;
&lt;p&gt;중요한 점은, 체스 말을 이동시키고 chess_pieces 리스트 안에 있는 체스 말의 정보도 업데이트해주어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;1724&quot; data-origin-height=&quot;1365&quot; width=&quot;654&quot; height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cryJZA/btqBezlJVGy/uAlxha69mp88JqFuXSJZa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cryJZA/btqBezlJVGy/uAlxha69mp88JqFuXSJZa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cryJZA/btqBezlJVGy/uAlxha69mp88JqFuXSJZa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcryJZA%2FbtqBezlJVGy%2FuAlxha69mp88JqFuXSJZa1%2Fimg.png&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;1724&quot; data-origin-height=&quot;1365&quot; width=&quot;654&quot; height=&quot;518&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;백준에서 프로그램을 종료할 때, exit()를 호출하였는데 자꾸 런타임 에러가 떴다. 구글링을 해보니 sys.exit(0)을 호출해야 런타임 에러 없이 정상적으로 채점이 되는 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less62_0&quot; data-id=&quot;62_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more62_1&quot; data-id=&quot;62_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content62_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less62_1&quot; data-id=&quot;62_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import sys

n, k = map(int, sys.stdin.readline().split())
board_info = [[0 for _ in range(n + 1)] for _ in range(n + 1)]
board = [[list() for _ in range(n + 1)] for _ in range(n + 1)]
chess_pieces = [0]

# initial board information
for i in range(1, n + 1):
	line = list(map(int, sys.stdin.readline().split()))
	for j in range(1, n + 1):
		board_info[i][j] = line[j - 1]

# initial chess pieces and board
for idx in range(1, k + 1):
	r, c, direction = map(int, sys.stdin.readline().split())
	chess_pieces.append([r, c, direction])
	board[r][c].append(idx)
	

# returns false if it's blue or out of boundary
def boundary_and_blue_check(_r, _c):
	if _r &amp;lt; 1 or _r &amp;gt; n or _c &amp;lt; 1 or _c &amp;gt; n:
		return False
	if board_info[_r][_c] == 2:
		return False
	return True


# returns current position if it's blue or out of boundary
def get_next_pos(_r, _c, _d):
	next_r, next_c, next_d = _r, _c, _d
	# if next position is white or red
	if boundary_and_blue_check(next_r + directions[next_d][0], next_c + directions[next_d][1]):
		next_r, next_c = next_r + directions[next_d][0], next_c + directions[next_d][1]
	# if next position is blue or out of boundary
	else:
		next_d = next_d + 1 if next_d % 2 else next_d - 1
		# if next position is white or red
		if boundary_and_blue_check(next_r + directions[next_d][0], next_c + directions[next_d][1]):
			next_r, next_c = next_r + directions[next_d][0], next_c + directions[next_d][1]
			
	return next_r, next_c, next_d


directions = ((), (0, 1), (0, -1), (-1, 0), (1, 0))
turn = 0
while turn &amp;lt;= 1000:
	turn += 1
	for idx, piece in list(enumerate(chess_pieces))[1:]:
		r, c, d = chess_pieces[idx][0], chess_pieces[idx][1], chess_pieces[idx][2]
		next_r, next_c, chess_pieces[idx][2] = get_next_pos(r, c, d)
		
		# no need to move chess pieces because it's blue or out of boundary
		if r == next_r and c == next_c:
			continue
		
		# split chess pieces into 2
		base_index = board[r][c].index(idx)
		board[r][c], temp_list = board[r][c][:base_index], board[r][c][base_index:]
		
		# white
		if board_info[next_r][next_c] == 0:
			# move and update position of chess pieces
			board[next_r][next_c].extend(temp_list)
			for i in temp_list:
				chess_pieces[i][0], chess_pieces[i][1] = next_r, next_c
		# red
		elif board_info[next_r][next_c] == 1:
			# move and update position of chess pieces
			board[next_r][next_c].extend(reversed(temp_list))
			for i in temp_list:
				chess_pieces[i][0], chess_pieces[i][1] = next_r, next_c
		
		if len(board[next_r][next_c]) &amp;gt;= 4:
			print(turn)
			sys.exit(0)
			
print(-1)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less62_1&quot; data-id=&quot;62_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>스택</category>
      <category>시뮬레이션</category>
      <category>알고리즘</category>
      <category>큐</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/62</guid>
      <comments>https://empty-cloud.tistory.com/62#entry62comment</comments>
      <pubDate>Tue, 14 Jan 2020 17:22:07 +0900</pubDate>
    </item>
    <item>
      <title>[운영체제] 동기화 (2)</title>
      <link>https://empty-cloud.tistory.com/61</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Bounded-Buffer 문제 (유한버퍼 문제)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;소비자와 생산자가 유한 개의 버퍼 자원을 공유하는 상황에서, 다음 문제를 해결하고자 한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;소비자와 생산자가 버퍼에 &lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;상호 배타적으로 접근&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;소비자는 버퍼에 &lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;원소가 한 개라도 있으면 버퍼를 소비&lt;/b&gt;&lt;/span&gt;해야 하고, 생산자는&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt; 버퍼에 원소가 없으면 원소를 생산&lt;/b&gt;&lt;/span&gt;해야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/civLhF/btqA7qDRIx2/ONZo5N8uerVc2vnqGk6eUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/civLhF/btqA7qDRIx2/ONZo5N8uerVc2vnqGk6eUk/img.png&quot; data-alt=&quot;Bounded-Buffer 문제 해결을 위한 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/civLhF/btqA7qDRIx2/ONZo5N8uerVc2vnqGk6eUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcivLhF%2FbtqA7qDRIx2%2FONZo5N8uerVc2vnqGk6eUk%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;518&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Bounded-Buffer 문제 해결을 위한 코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위의 문제를 해결하기 위한 조건은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;생산자가 먼저 실행된 적이 있어야 하고, 생산자의 실행 횟수가 소비자보다 많아야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;위 문제를 해결하기 위해 사용하는 변수는 다음 세 가지이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;세마포어 mutex(= 1):&lt;/b&gt; 생산자와 소비자의 &lt;span style=&quot;color: #006dd7;&quot;&gt;상호배제&lt;/span&gt;를 위한 변수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세마포어 empty(= n):&lt;/b&gt; 비어있는 버퍼의 개수를 나타내는 변수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세마포어 full(= 0):&lt;/b&gt; 버퍼가 차있는 개수를 나타내는 변수&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reader-Writer 문제 (독자-저자 문제)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;여러 개의 reader는 공유 데이터를 동시에 읽는 것이 가능한 반면에, writer는 reader가 공유 데이터를 읽는 동안 공유 데이터에 접근해서 수정할 수 없다.&lt;/p&gt;
&lt;p&gt;Reader-Writer 문제는 2가지가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;First reader-writer problem:&lt;/b&gt; writer가 대기하고 있다고 해서 reader가 다른 reader를 기다리면 안 된다. 마지막 reader가 공유자원을 release 하면 writer가 임계구역으로 진입한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Second reader-writer problem:&lt;/b&gt; 만약 writer가 대기하고 있다면, 어떠한 새로운 reader도 실행될 수 없다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;위 두 가지 모두 starvation의 가능성이 있다&lt;/span&gt;.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새로운 reader가 계속 들어오면 writer는 계속 기다려야 한다.&lt;/li&gt;
&lt;li&gt;새로운 writer가 계속 들어오면 reader는 계속 기다려야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;691&quot; width=&quot;634&quot; height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGk6E9/btqA7qDUPdq/mKkkz8Kl6KFPMdVUkRkMd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGk6E9/btqA7qDUPdq/mKkkz8Kl6KFPMdVUkRkMd0/img.png&quot; data-alt=&quot;First reader-writer 문제 해결을 위한 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGk6E9/btqA7qDUPdq/mKkkz8Kl6KFPMdVUkRkMd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGk6E9%2FbtqA7qDUPdq%2FmKkkz8Kl6KFPMdVUkRkMd0%2Fimg.png&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;691&quot; width=&quot;634&quot; height=&quot;396&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;First reader-writer 문제 해결을 위한 코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;First reader-writer 문제 해결을 위해 사용하는 변수는 다음 세 가지이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;세마포어 rw_mutex (= 1):&lt;/b&gt; &lt;u&gt;reader와 writer의 &lt;span style=&quot;color: #006dd7;&quot;&gt;상호배제&lt;/span&gt;를 위한 변수&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세마포어 mutex (= 1):&lt;/b&gt; read_count를 갱신하기 위한 &lt;span style=&quot;color: #333333;&quot;&gt;reader 간의&lt;u&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;상호배제&lt;/span&gt;를 위한 변수&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정수 read_count (= 0):&lt;/b&gt; 공유자원을 읽고 있는 reader의 개수를 나타내는 변수&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;위의 코드는 reader가 수행되는 동안 writer가 임계구역에 진입하는 것을 배제함으로써 &lt;b&gt;First reader-writer 문제를 해결&lt;/b&gt;하지만, &lt;span style=&quot;color: #ee2323;&quot;&gt;이는 writer에게 starvation을 야기할 수 있다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dining-Philosophers 문제 (식사하는 철학자 문제)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bO3OaV/btqBeAEB8Ay/HXrGdeEqt08d3WSThtRbk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bO3OaV/btqBeAEB8Ay/HXrGdeEqt08d3WSThtRbk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bO3OaV/btqBeAEB8Ay/HXrGdeEqt08d3WSThtRbk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbO3OaV%2FbtqBeAEB8Ay%2FHXrGdeEqt08d3WSThtRbk0%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;316&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;철학자 5명이 원형 테이블에 앉아있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;각 철학자들은 식사를 하기 위해서 젓가락 2개가 필요하며, 젓가락은 철학자의 왼쪽과 오른쪽에 위치한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;각 철학자들은 한 번에 한 개의 젓가락만 집을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;철학자가 식사를 하지 않는 동안에는 생각을 하는데, 생각을 하는 동안 다른 철학자들과 교류하지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여기서 일반적인 해결법은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;469&quot; data-origin-height=&quot;431&quot; width=&quot;335&quot; height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eA3Uqz/btqA7rv4ZQj/Ukrav6I1rmGrBtYFWK8td0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eA3Uqz/btqA7rv4ZQj/Ukrav6I1rmGrBtYFWK8td0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eA3Uqz/btqA7rv4ZQj/Ukrav6I1rmGrBtYFWK8td0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeA3Uqz%2FbtqA7rv4ZQj%2FUkrav6I1rmGrBtYFWK8td0%2Fimg.png&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;469&quot; data-origin-height=&quot;431&quot; width=&quot;335&quot; height=&quot;308&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;왼쪽의 코드는 각 철학자들이 자신의 왼쪽 젓가락을 먼저 집고, 오른쪽 젓가락을 집는다.&lt;/p&gt;
&lt;p&gt;젓가락을 다 집은 후, 식사를 하고 다시 왼쪽 젓가락을 놓고 오른쪽 젓가락을 놓는다.&lt;/p&gt;
&lt;p&gt;만약 한 명의 철학자가 젓가락을 모두 집어 든다면 그 철학자는 식사할 수 있고, 다른 철학자는 그 철학자의 식사가 끝날 때까지 대기한다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;하지만 모든 철학자가 동시에 자신의 왼쪽의 젓가락을 집어 드는 경우 &lt;span style=&quot;color: #006dd7;&quot;&gt;Deadlock&lt;/span&gt;이 발생한다&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;따라서 이 방법은 올바른 해결법이 아니다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Deadlock&lt;/span&gt; 문제를 해결하기 위해 다음과 같은 3가지 방법이 존재한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5명의 철학자 중 4명만 식사를 할 수 있게 한다.&lt;/li&gt;
&lt;li&gt;양쪽의 젓가락을 집을 수 있을 때, 동시에 그 젓가락을 집게 한다.&lt;/li&gt;
&lt;li&gt;홀수번째 철학자는 왼쪽-오른쪽 순으로, 짝수번째 철학자는 오른쪽-왼쪽 순으로 젓가락을 집게 한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>컴퓨터공학/운영체제</category>
      <category>Bounded Buffer</category>
      <category>Deadlock</category>
      <category>Dining Philosopher</category>
      <category>Reader Writer</category>
      <category>Synchronization</category>
      <category>운영체제</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/61</guid>
      <comments>https://empty-cloud.tistory.com/61#entry61comment</comments>
      <pubDate>Tue, 14 Jan 2020 14:21:01 +0900</pubDate>
    </item>
    <item>
      <title>[운영체제] 동기화 (1)</title>
      <link>https://empty-cloud.tistory.com/60</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Bounded-Buffer 문제 (유한 버퍼 문제)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btf0fj/btqAZOkykQr/36ySRsRUV82IF42P12J2Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btf0fj/btqAZOkykQr/36ySRsRUV82IF42P12J2Yk/img.png&quot; data-alt=&quot;생산자와 소비자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btf0fj/btqAZOkykQr/36ySRsRUV82IF42P12J2Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbtf0fj%2FbtqAZOkykQr%2F36ySRsRUV82IF42P12J2Yk%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;431&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생산자와 소비자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;생산자(Producer)는 데이터를 생성하고, 소비자(Consumer)는 데이터를 소비한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;407&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/diqMq7/btqA057dNiF/NpXoGkXAOKWPuDfrB6DEE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/diqMq7/btqA057dNiF/NpXoGkXAOKWPuDfrB6DEE1/img.png&quot; data-alt=&quot;생산자가 데이터를 생산하면 in이 증가하고, 소비자가 데이터를 소비하면 out이 증가한다. in과 out이 같은 경우, 버퍼가 가득 찼는지 비어있는지 확인할 수 없다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/diqMq7/btqA057dNiF/NpXoGkXAOKWPuDfrB6DEE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdiqMq7%2FbtqA057dNiF%2FNpXoGkXAOKWPuDfrB6DEE1%2Fimg.png&quot; data-filename=&quot;그림2.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;407&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생산자가 데이터를 생산하면 in이 증가하고, 소비자가 데이터를 소비하면 out이 증가한다. in과 out이 같은 경우, 버퍼가 가득 찼는지 비어있는지 확인할 수 없다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;in과 out의 값으로는 버퍼에 있는 데이터의 양을 알 수가 없다. (위의 그림 참조) 따라서 counter 변수를 사용한다. 하지만 &lt;u&gt;counter 변수는 생산자와 소비자가 동시에 접근하므로&lt;/u&gt; &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Race condition&lt;/span&gt;&lt;/b&gt;이 발생한다. 따라서 동기화가 필요하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Race condition&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;여러 프로세스(또는 스레드)가 공유자원에 동시에 접근할 때, 접근 순서에 따라 결과가 달라질 수 있는 상황&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Synchronizaiton (동기화)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Multi-threaded application
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;스레드는 프로세스 안에서 메모리를 공유한다. (&lt;span style=&quot;color: #ee2323;&quot;&gt;스택은 별개로 가진다.&lt;/span&gt;) 데이터 손상을 막기 위해서는 동기화가 필요하다.
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;특히, &lt;span style=&quot;color: #006dd7;&quot;&gt;Silent corruption&lt;span style=&quot;color: #333333;&quot;&gt;에 주의가 필요하다.&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;OS나 디스크 펌웨어가 데이터가 잘못됐다고 인식하지 못하는 corruption. 심각한 에러를 초래할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Kernel mode&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;커널 자료구조 업데이트&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;여러 프로세스가 동시에 커널 모드로 들어갈 수는 있지만 동시에 커널 데이터는 수정이 불가능해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Preemptive 커널 vs. Nonpreemtive 커널
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;Nonpreemtive 커널
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;Race condition이 없다.&lt;/li&gt;
&lt;li&gt;대신 반응이 느리다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Preemptive 커널
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;Real time system에서 빠른 응답이 필요하기 때문에 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Critical Section 문제 (임계구역 문제)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;334&quot; width=&quot;300&quot; height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4wYZW/btqA4z6QEgc/CkT6NZWmAcwkgqpWbhPxbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4wYZW/btqA4z6QEgc/CkT6NZWmAcwkgqpWbhPxbk/img.png&quot; data-alt=&quot;일반적인 프로세스의 실행구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4wYZW/btqA4z6QEgc/CkT6NZWmAcwkgqpWbhPxbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4wYZW%2FbtqA4z6QEgc%2FCkT6NZWmAcwkgqpWbhPxbk%2Fimg.png&quot; data-filename=&quot;그림3.png&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;334&quot; width=&quot;300&quot; height=&quot;212&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;일반적인 프로세스의 실행구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Entry section
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;임계구역으로 진입하기 전의 구역&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Critical section (임계구역)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;여러 프로세스들이 공유자원을 수정할 가능성이 있는 코드 구역&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;만약 하나의 프로세스가 임계구역에 있다면, 다른 어떤 프로세스도 진입해서는 안된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Exit section
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;임계구역을 벗어남을 알리기 위한 구역&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Remainder section
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;코드의 나머지 부분&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Critical Section 문제의 3가지 해결 조건&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;아래 3가지 요구사항을 만족시켜서 Critical Section 문제를 해결하겠다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Mutual exclusion (상호배제)&lt;/span&gt;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;임계구역에서 한 개의 프로세스가 작업 중일 때, 다른 프로세스는 접근할 수 없다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Progress (진행)&lt;/span&gt;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;임계구역에서 작업 중인 프로세스가 없고, 임계구역으로 진입하려는 프로세스가 있다면 하나를 적절히 선택하여 진입할 수 있게 한다. 선택은 즉각적이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Bounded waiting (유한대기)&lt;/span&gt;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;다른 프로세스들의 &lt;span style=&quot;color: #006dd7;&quot;&gt;Starvation&lt;/span&gt;을 방지하기 위해, 한 번 임계구역에 들어간 프로세스는 다시 임계구역에 들어갈 때 횟수에 제한을 두어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Critical Section의 소프트웨어적 해결방법&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Peterson's Algorithm&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;351&quot; width=&quot;362&quot; height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kx3DJ/btqA3dKdyEd/GfAcik6okklZievia6OTp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kx3DJ/btqA3dKdyEd/GfAcik6okklZievia6OTp0/img.png&quot; data-alt=&quot;프로세스 i의 실행구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kx3DJ/btqA3dKdyEd/GfAcik6okklZievia6OTp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fkx3DJ%2FbtqA3dKdyEd%2FGfAcik6okklZievia6OTp0%2Fimg.png&quot; data-filename=&quot;그림4.png&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;351&quot; width=&quot;362&quot; height=&quot;289&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로세스 i의 실행구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;프로세스가 2개일 때만 사용 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프로세스 i와 프로세스 j가 공유하는 자원&lt;/span&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;int turn: 임계구역에 진입할 프로세스는 누구인가&lt;/li&gt;
&lt;li&gt;boolean flag[2]: 임계구역에 프로세스가 진입할 준비가 되어있는가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Mutual exclusion (상호배제) - 만족&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;프로세스 i가 임계구역의 진입할 준비가 되었고, turn = j로 설정함으로써 프로세스 i는 무한루프에 빠져 대기상태가 되고, 프로세스 j가 임계구역에 진입한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Progress (진행) - 만족&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;프로세스 j가 임계구역에서 작업을 마치고 flag[j] = false가 되면 프로세스 i는 곧바로 임계구역으로 진입한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bounded waiting (유한대기) - 만족&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;프로세스 j가 임계구역에서 작업을 마치면 프로세스 i가 임계구역으로 진입하여 기아 현상이 사라진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;피터슨 알고리즘의 단점으로는 아무 일도 안 하는 대기상태를 while문으로 구현하였는데, 이는 &lt;span style=&quot;color: #006dd7;&quot;&gt;busy waiting&lt;/span&gt;으로써 CPU 자원을 낭비한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Critical Section의 하드웨어적 해결방법&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;test_and_set&lt;/h3&gt;
&lt;p&gt;임계구역에 프로세스가 있을 때 lock은 true, 프로세스가 없으면 lock은 false이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;261&quot; width=&quot;324&quot; height=&quot;143&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PQvdT/btqA2a1P0O7/dCf0b3mRrb4Kt8orR3Bpgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PQvdT/btqA2a1P0O7/dCf0b3mRrb4Kt8orR3Bpgk/img.png&quot; data-alt=&quot;test_and_set 인스트럭션 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PQvdT/btqA2a1P0O7/dCf0b3mRrb4Kt8orR3Bpgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPQvdT%2FbtqA2a1P0O7%2FdCf0b3mRrb4Kt8orR3Bpgk%2Fimg.png&quot; data-filename=&quot;그림5.png&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;261&quot; width=&quot;324&quot; height=&quot;143&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;test_and_set 인스트럭션 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;485&quot; width=&quot;394&quot; height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v4TtS/btqA4AeaGmc/94ddLK23gn5wMB8X6vRF50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v4TtS/btqA4AeaGmc/94ddLK23gn5wMB8X6vRF50/img.png&quot; data-alt=&quot;test_and_set을 사용한 프로세스의 실행구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v4TtS/btqA4AeaGmc/94ddLK23gn5wMB8X6vRF50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv4TtS%2FbtqA4AeaGmc%2F94ddLK23gn5wMB8X6vRF50%2Fimg.png&quot; data-filename=&quot;그림6.png&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;485&quot; width=&quot;394&quot; height=&quot;280&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;test_and_set을 사용한 프로세스의 실행구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;만약 임계구역에 어떤 프로세스도 없는 상태에서 test_and_set을 호출하면 결괏값은 false를 반환하고, lock은 true가 된다. 따라서 임계구역의 진입하려는 프로세스는 while문을 빠져나오고 임계구역에 진입하게 된다.&lt;/p&gt;
&lt;p&gt;임계구역에서 작업을 마친 프로세스는 lock = false를 통하여 다른 프로세스가 임계구역에 진입하기 위해 경쟁할 수 있도록 해준다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;위의 코드는 starvation의 가능성이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;compare_and_swap&lt;/h3&gt;
&lt;p&gt;임계구역에 프로세스가 있을 때 lock은 1, 프로세스가 없을 때 lock은 0이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림7.png&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;271&quot; width=&quot;577&quot; height=&quot;169&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daig2k/btqA2OYvTkW/R2snaEoMWVzYk8ipto9CDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daig2k/btqA2OYvTkW/R2snaEoMWVzYk8ipto9CDK/img.png&quot; data-alt=&quot;compare_and_swap 인스트럭션 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daig2k/btqA2OYvTkW/R2snaEoMWVzYk8ipto9CDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdaig2k%2FbtqA2OYvTkW%2FR2snaEoMWVzYk8ipto9CDK%2Fimg.png&quot; data-filename=&quot;그림7.png&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;271&quot; width=&quot;577&quot; height=&quot;169&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;compare_and_swap 인스트럭션 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;485&quot; width=&quot;419&quot; height=&quot;267&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2ObqF/btqA1zngwYl/KjjqPzeOHgSW4iJjA7r8C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2ObqF/btqA1zngwYl/KjjqPzeOHgSW4iJjA7r8C1/img.png&quot; data-alt=&quot;compare_and_swap을 사용한 프로세스의 실행구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2ObqF/btqA1zngwYl/KjjqPzeOHgSW4iJjA7r8C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2ObqF%2FbtqA1zngwYl%2FKjjqPzeOHgSW4iJjA7r8C1%2Fimg.png&quot; data-filename=&quot;그림8.png&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;485&quot; width=&quot;419&quot; height=&quot;267&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;compare_and_swap을 사용한 프로세스의 실행구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;test_and_set과 다르게 3개의 매개변수가 필요하다. lock의 메모리 주소, lock의 기댓값 그리고 lock을 설정할 값이다.&lt;/p&gt;
&lt;p&gt;만약 임계구역에 프로세스가 없다면 compare_and_swap은 0을 반환하고, lock을 1로 설정한다. 따라서 임계구역에 진입하려는 프로세스는 while문을 빠져나오고 임계구역에 진입하게 된다.&lt;/p&gt;
&lt;p&gt;임계구역에서 작업을 마친 프로세스는 lock = 0를 통하여 다른 프로세스가 임계구역에 진입하기 위해 경쟁할 수 있도록 해준다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;위의 코드는 starvation의 가능성이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Mutex와 Semaphore&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Mutex&lt;/h3&gt;
&lt;p&gt;위에서 설명한 하드웨어적 해결방법들은 프로그래머가 다루기 어렵고, 플랫폼에 종속적이다.&lt;/p&gt;
&lt;p&gt;따라서 대부분의 운영체제는 프로그래머를 위해 API를 제공해주는데, &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;mutex&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림9.png&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XxPOK/btqA57CCgF6/LGVjRzGZLsDDTkGsI9HDck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XxPOK/btqA57CCgF6/LGVjRzGZLsDDTkGsI9HDck/img.png&quot; data-alt=&quot;acquire와 release, 그리고 프로세스의 실행구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XxPOK/btqA57CCgF6/LGVjRzGZLsDDTkGsI9HDck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXxPOK%2FbtqA57CCgF6%2FLGVjRzGZLsDDTkGsI9HDck%2Fimg.png&quot; data-filename=&quot;그림9.png&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;271&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;acquire와 release, 그리고 프로세스의 실행구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Mutex도 test_and_set과 비슷한 구조로 작동함을 알 수 있다.&lt;/p&gt;
&lt;p&gt;Mutex의 acquire 함수를 보면, 임계구역에 진입하려는 프로세스들을 blocking 하기 위해&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;busy waiting&lt;/span&gt;을 사용하는 것을 알 수 있다. 이를 &lt;span style=&quot;color: #006dd7;&quot;&gt;spinlock&lt;/span&gt;이라고 부르며 마찬가지로 &lt;span style=&quot;color: #ee2323;&quot;&gt;CPU 사이클을 낭비한다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Semaphore&lt;/h3&gt;
&lt;p&gt;Mutex보다 조금 더 강력한 대안으로 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;semaphore&lt;/b&gt;&lt;/span&gt;가 있다. S&lt;span style=&quot;color: #333333;&quot;&gt;emaphore&lt;/span&gt;는 &lt;span style=&quot;color: #ee2323;&quot;&gt;정수형 변수 S에 대해 wait, signal이라는 atomic 한 함수를 사용한다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Semaphore에는 2가지가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Binary semaphore&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;S의 값으로 0과 1만 사용하며, mutex lock과 비슷하게 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Counting semaphore&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;S는 사용 가능한 자원의 개수를 나타내며, 2 이상의 정수 값을 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림10.png&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvz1TV/btqA05z0oP3/XLDxs1U8Ngk8DCUNon2et1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvz1TV/btqA05z0oP3/XLDxs1U8Ngk8DCUNon2et1/img.png&quot; data-alt=&quot;wait와 signal 그리고 프로세스의 실행구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvz1TV/btqA05z0oP3/XLDxs1U8Ngk8DCUNon2et1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcvz1TV%2FbtqA05z0oP3%2FXLDxs1U8Ngk8DCUNon2et1%2Fimg.png&quot; data-filename=&quot;그림10.png&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;271&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;wait와 signal 그리고 프로세스의 실행구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;사용 가능한 자원 S가 0보다 크다면 임계구역에 진입할 수 있고, 프로세스가 임계구역에 진입한다면 S를 감소시킨다.&lt;/p&gt;
&lt;p&gt;만약 프로세스가 임계구역에 진입하려고 할 때 S가 0보다 같거나 작다면(= 사용 가능한 자원이 없다면) 프로세스는 block 된다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;span style=&quot;color: #ee2323;&quot;&gt;위의 semaphore의 문제점 역시 spinlock으로 인한 CPU 사이클 낭비이다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;따라서 semaphore에 큐를 만들고, 이 큐를 통해 CPU가 스케줄링을 하도록 조작하는 방법이 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림11.png&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dm5lAb/btqA2O5oOET/4zXuRkAq8T63Uu4zJhKwi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dm5lAb/btqA2O5oOET/4zXuRkAq8T63Uu4zJhKwi0/img.png&quot; data-alt=&quot;변경된 wait와 signal&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dm5lAb/btqA2O5oOET/4zXuRkAq8T63Uu4zJhKwi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdm5lAb%2FbtqA2O5oOET%2F4zXuRkAq8T63Uu4zJhKwi0%2Fimg.png&quot; data-filename=&quot;그림11.png&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;310&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변경된 wait와 signal&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;wait()&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;프로세스를 semaphore의 waiting queue에 넣는다.&lt;/li&gt;
&lt;li&gt;프로세스를 waiting state로 바꾼다.&lt;/li&gt;
&lt;li&gt;CPU 스케줄러는 &lt;span style=&quot;color: #ee2323;&quot;&gt;semaphore의 waiting queue에 없는, 다음에 실행할 프로세스를 선택한다&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;signal()&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;Semaphore의 waiting queue 안에 있는 프로세스 한 개를 ready state로 바꾼다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;프로세스를 ready queue로 삽입하여 CPU가 스케줄링할 수 있도록 한다&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Mutex와 Semaphore의 문제점&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;아래와 같은 경우 &lt;span style=&quot;color: #006dd7;&quot;&gt;Deadlock&lt;/span&gt;이 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림12.png&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;304&quot; width=&quot;338&quot; height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rf8Kj/btqA04A8Z6v/jDm8Q6Wqkltrqj2MS74ndK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rf8Kj/btqA04A8Z6v/jDm8Q6Wqkltrqj2MS74ndK/img.png&quot; data-alt=&quot;Mutex와 Semaphore의 Deadlock 발생조건&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rf8Kj/btqA04A8Z6v/jDm8Q6Wqkltrqj2MS74ndK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frf8Kj%2FbtqA04A8Z6v%2FjDm8Q6Wqkltrqj2MS74ndK%2Fimg.png&quot; data-filename=&quot;그림12.png&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;304&quot; width=&quot;338&quot; height=&quot;231&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mutex와 Semaphore의 Deadlock 발생조건&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;또는, Semaphore의 ready queue가 FIFO가 아닌 &lt;span style=&quot;color: #ee2323;&quot;&gt;LIFO로 구현되어 있다면 starvation이 발생할 수 있다&lt;/span&gt;.&lt;/p&gt;</description>
      <category>컴퓨터공학/운영체제</category>
      <category>Bounded Buffer</category>
      <category>compare_and_swap</category>
      <category>Mutex</category>
      <category>Peterson's Algorithm</category>
      <category>semaphore</category>
      <category>Synchronization</category>
      <category>test_and_set</category>
      <category>운영체제</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/60</guid>
      <comments>https://empty-cloud.tistory.com/60#entry60comment</comments>
      <pubDate>Fri, 10 Jan 2020 00:05:34 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 5] Gerrit 사용하기 (1)</title>
      <link>https://empty-cloud.tistory.com/59</link>
      <description>&lt;p&gt;이번에는 우리가 OpenStack에 contribute하기 전에 Gerrit을 어떻게 사용해야 하는지 알아볼 것입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Gerrit 흐름도&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCMTbv/btqARyhNcBL/FmgVTuOsx4Dk25GqgMfLUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCMTbv/btqARyhNcBL/FmgVTuOsx4Dk25GqgMfLUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCMTbv/btqARyhNcBL/FmgVTuOsx4Dk25GqgMfLUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCMTbv%2FbtqARyhNcBL%2FFmgVTuOsx4Dk25GqgMfLUK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위의 그림은 Gerrit을 통한 코드 리뷰의 흐름을 나타낸 것입니다. 위의 그림을 간단하게 설명하자면 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;코드를 수정하고자 하는 프로젝트를 로컬 환경으로 clone합니다.&lt;/li&gt;
&lt;li&gt;로컬 환경에서 수정하고자 하는 버그에 대해서 브랜치를 생성합니다.&lt;/li&gt;
&lt;li&gt;변경사항에 대해 저장하고, 유닛 테스트를 진행한 다음, git commit을 실행합니다. (&lt;b&gt;가장 첫 번째 커밋만 git commit으로 로컬 환경에 변경사항을 저장합니다.&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;git review를 통해 Gerrit 리뷰시스템에 변경사항을 제출합니다.&lt;/li&gt;
&lt;li&gt;자동 테스트 툴을 통해, 빌드 및 테스트를 진행하고, 제출한 코드를 리뷰 받습니다.&lt;/li&gt;
&lt;li&gt;기존의 변경사항을 다시 수정해야할 경우, 코드를 변경하고 git commit --amend를 통해 다시 변경사항을 제출합니다. (&lt;b&gt;반드시 --amend 옵션을 붙여야합니다.&lt;/b&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Bug에 대해서 작업하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;하나의 프로젝트에 대해서 버그 리포트는 Launchpad(&lt;a href=&quot;https://bugs.launchpad.net&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bugs.launchpad.net&lt;/a&gt;&lt;span style=&quot;color: #333333;&quot;&gt;/&amp;lt;프로젝트&amp;gt;)나 StoryBoard(&lt;a href=&quot;https://storyboard.openstack.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://storyboard.openstack.org&lt;/a&gt;)에 기록됩니다. 컨트리뷰터들은 정기적으로 완료할 작업을 찾을 때 이러한 버그 리포트들을 리뷰할 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;버그 상태에 대한 정보는 여기에 문서화 되어있습니다: &lt;a href=&quot;https://docs.openstack.org/project-team-guide/bugs.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.openstack.org/project-team-guide/bugs.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;작업하고싶은 버그를 발견한다면 그 버그를 자신에게 할당해도 됩니다. 리뷰를 업로드 할 때, Launchpad와 StoryBoard에 자동 업데이트를 위해서 커밋 메시지 속에 버그를 포함시키세요. Launchpad에서 사용 가능한 옵션은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;Closes-Bug: #######
Partial-Bug: #######
Related-Bug: #######&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그리고 StoryBoard에서는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;Task: ######
Story: ######&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항 시작하기&lt;/h3&gt;
&lt;p&gt;작업을 저장할 브랜치를 생성하고, 그 브랜치로 전환하세요. 만약 blueprint에 대해서 작업하고 있다면, 브랜치의 이름을 bp/BLUEPRINT로 설정하세요. 여기서 BLUEPRINT는 Launchpad에서 blueprint의 이름입니다. (예: bp/authentication) 버그에 대한 일반적인 관습은 브랜치의 이름을 bug/BUG-NUMBER로 지정하는 것입니다. (예: bug/1234567)&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;git checkout -b TOPIC-BRANCH&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항 커밋하기&lt;/h3&gt;
&lt;p&gt;커밋 메시지의 타이틀은 50자 이내로 작성해야 합니다. 그 다음에 오는 문단은 변경사항에 대해 더 자세하게 설명해야 합니다.&lt;/p&gt;
&lt;p&gt;만약 변경사항이 blueprint 또는 버그를 처리하는 경우, 다음 구문을 사용해서 커밋 메시지 안에 언급하도록 하세요.&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;Implements: blueprint BLUEPRINT
Closes-Bug: ####### (Partial-Bug or Related-Bug are options)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;예를 들면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;Adds keystone support

...Long multiline description of the change...

Implements: blueprint authentication
Closes-Bug: #123456
Change-Id: I4946a16d27f712ae2adf8441ce78e6c0bb0bb657&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;대부분의 경우 git-review가 설치한 Gerrit 커밋 훅에 의해서 Change-Id 라인이 자동으로 추가되는 점에 유의하세요. 이미 커밋을 했는데 Change-Id가 추가되지 않은 경우 Gerrit 설정 단계를 다시 수행하고 다음 명령을 실행하세요: &lt;b&gt;git commit --amend.&lt;/b&gt; 커밋 훅은 우리가 실제로 아무 변경사항도 만들지 않았어도, 커밋 메시지 수정을 마치면 자동으로 Change-Id를 추가합니다. Change-Id는 절대로 변경하지 마세요. Gerrit이 혼동할 수 있습니다.&lt;/p&gt;
&lt;p&gt;변경사항을 만들고, 커밋하세요. (&lt;b&gt;아직 리뷰를 제출하지는 않았습니다.&lt;/b&gt;)&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;git commit -a&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;마스터 브랜치에서 변경사항을 만들지 마세요. 그렇게 하면 upstream으로부터 새로운 변경사항을 pull 할 때 충돌이 발생하고, merge 커밋은 Gerrit에 의해 거절됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Unit Test 실행하기&lt;/h3&gt;
&lt;p&gt;변경사항을 제출하기 전에, 우리는 꼭 테스트를 해봐야 합니다. OpenStack 프로젝트에서 파이썬 기반 유닛 테스트를 실행하는 법을 배우려면 다음 주소를 참고하세요: &lt;a href=&quot;https://docs.openstack.org/project-team-guide/project-setup/python.html#running-python-unit-tests&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Running Python Unit Tests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리뷰를 위해 변경사항 제출하기&lt;/h3&gt;
&lt;p&gt;로컬 레포지토리로 변경사항을 커밋했다면, 코드 리뷰를 위해 Gerrit으로 전송하기 위해 필요한 것은 다음 명령어 한 줄이면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;git review&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 작업이 끝나면 제출한 변경사항에 대해 자동화 된 테스트가 실행될 것이고, 다른 개발자가 검토를 할 것입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항 업데이트 하기&lt;/h3&gt;
&lt;p&gt;만약 코드 리뷰 과정에서 추가적인 변경을 제안하는 경우, 기존 커밋을 변경하고 수정하세요. 커밋 메시지 아래에 있는 Change-Id 줄은 그대로 두세요. Gerrit은 이것이 기존 변경사항에 대한 업데이트된 패치셋이라는 걸 알고있습니다.&lt;/p&gt;
&lt;pre class=&quot;plaintext&quot;&gt;&lt;code&gt;git commit -a --amend
git review&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://docs.openstack.org/infra/manual/developers.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.openstack.org/infra/manual/developers.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/contributors/code-and-documentation/using-gerrit.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.openstack.org/contributors/code-and-documentation/using-gerrit.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>gerrit</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/59</guid>
      <comments>https://empty-cloud.tistory.com/59#entry59comment</comments>
      <pubDate>Sun, 5 Jan 2020 22:47:53 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 더 맵게</title>
      <link>https://empty-cloud.tistory.com/58</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42626&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;더_맵게.PNG&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdMkWR/btqAU7iWStz/8qUdsRNyVuHR2qShIk2KMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdMkWR/btqAU7iWStz/8qUdsRNyVuHR2qShIk2KMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdMkWR/btqAU7iWStz/8qUdsRNyVuHR2qShIk2KMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdMkWR%2FbtqAU7iWStz%2F8qUdsRNyVuHR2qShIk2KMK%2Fimg.png&quot; data-filename=&quot;더_맵게.PNG&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;390&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more58_0&quot; data-id=&quot;58_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content58_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less58_0&quot; data-id=&quot;58_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;힙&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;힙 자료구조를 사용해서 우선순위 큐를 구현하는 것이 문제의 의도이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;주어진 스코빌 리스트를 힙으로 변경한다. (7~8번째 줄)&lt;/li&gt;
&lt;li&gt;문제에서 주어진 방식대로 음식 2개를 섞어 새로운 음식을 만들고, 이 때의 스코빌 지수를 추가한다. (11~15번째 줄)&lt;/li&gt;
&lt;li&gt;모든 음식의 스코빌 지수가 K보다 높아야하므로, 힙의 루트가 K보다 작을 동안(= 힙의 최소값이 K보다 커지면 모든 음식의 스코빌 지수가 K보다 크다) 반복한다. (9~10번째 줄)&lt;/li&gt;
&lt;li&gt;더이상 섞을 음식이 없고, 스코빌 지수가 K보다 낮다면 -1을 반환한다. (17~18번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less58_0&quot; data-id=&quot;58_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more58_1&quot; data-id=&quot;58_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content58_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less58_1&quot; data-id=&quot;58_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1578211603080&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq


def solution(scoville, K):
	answer = 0
	
	# make scoville list heap
	heapq.heapify(scoville)
	# while minimum of the heap is lower than K
	while scoville[0] &amp;lt; K:
		# mix 2 foods
		a = heapq.heappop(scoville)
		b = heapq.heappop(scoville)
		heapq.heappush(scoville, a + (b * 2))
		answer += 1
		
		if len(scoville) == 1 and scoville[0] &amp;lt; K:
			return -1
		
	return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less58_1&quot; data-id=&quot;58_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>알고리즘</category>
      <category>프로그래머스</category>
      <category>힙</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/58</guid>
      <comments>https://empty-cloud.tistory.com/58#entry58comment</comments>
      <pubDate>Sun, 5 Jan 2020 17:13:02 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 주식가격</title>
      <link>https://empty-cloud.tistory.com/57</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42584&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;주식가격.PNG&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2gYLe/btqAQOZqDFa/yIcu2Z2GudEgPFxrDALAxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2gYLe/btqAQOZqDFa/yIcu2Z2GudEgPFxrDALAxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2gYLe/btqAQOZqDFa/yIcu2Z2GudEgPFxrDALAxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2gYLe%2FbtqAQOZqDFa%2FyIcu2Z2GudEgPFxrDALAxk%2Fimg.png&quot; data-filename=&quot;주식가격.PNG&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;393&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more57_0&quot; data-id=&quot;57_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content57_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less57_0&quot; data-id=&quot;57_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;스택/큐&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;주식이 시간이 지남에 따라 가격이 떨어지지 않은 시간이 얼마인지 구하는 문제이다.&lt;/p&gt;
&lt;p&gt;현재 시간에서 미래에 가격이 떨어지는 시간까지 탐색을 해야하기 때문에 O(n^2)이 나올거라고 생각했다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 시간에서의 주식 가격에 대해서 (5~6번째 줄)&lt;/li&gt;
&lt;li&gt;주식 가격이 떨어지지 않는 시간을 구한다. (8~15번째 줄)&lt;/li&gt;
&lt;li&gt;각 시점에서의 주식 가격이 떨어지지 않는 시간을 업데이트한다. (17번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여기서 눈여겨 볼 점은, 11~15번째 줄이다. 먼저 시간부터 센 다음, 만약 주식 가격이 떨어지면 break를 통해 반복문을 벗어난다.&lt;/p&gt;
&lt;p&gt;이는 예제 입력을 보면 알 수 있다.&lt;/p&gt;
&lt;p&gt;주식 가격이 상승을 하던 하락을 하던 일단 1초는 지나가기 때문에 시간을 먼저 세는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less57_0&quot; data-id=&quot;57_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more57_1&quot; data-id=&quot;57_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content57_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less57_1&quot; data-id=&quot;57_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1578077322565&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(prices):
	answer = [0 for _ in range(len(prices))]
	length = len(prices)
	
	# for all stock prices
	for i, p in enumerate(prices):
		
		# estimate duration
		duration = 0
		for j in range(i + 1, length, 1):
			# count time unconditionally
			duration += 1
			# if a stock price drops
			if prices[j] &amp;lt; p:
				break
		
		answer[i] = duration
		
	return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less57_1&quot; data-id=&quot;57_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>큐</category>
      <category>프로그래머스</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/57</guid>
      <comments>https://empty-cloud.tistory.com/57#entry57comment</comments>
      <pubDate>Sat, 4 Jan 2020 04:02:19 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 쇠막대기</title>
      <link>https://empty-cloud.tistory.com/56</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42585&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/roXZO/btqAQk4eLcH/hhp7nr1s3clmNMGLifxv30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/roXZO/btqAQk4eLcH/hhp7nr1s3clmNMGLifxv30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/roXZO/btqAQk4eLcH/hhp7nr1s3clmNMGLifxv30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FroXZO%2FbtqAQk4eLcH%2Fhhp7nr1s3clmNMGLifxv30%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;337&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more56_0&quot; data-id=&quot;56_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content56_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less56_0&quot; data-id=&quot;56_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;스택/큐&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;문제를 해결하는데 스택이 사용되긴 했지만, 오히려 개념은 DP에 가까운 느낌이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;문자열을 하나씩 읽을 때마다, 레이저를 만나게 되면 잘린 막대기가 몇 개인지 판단하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;문제를 푼 로직은 다음과 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;레이저는 &quot;()&quot;로 구분되므로, 더 쉬운 이해를 위해서 다른 문자 하나로 치환한다. (나의 경우 '.'로 치환했다.)&lt;/li&gt;
&lt;li&gt;문자열을 읽으면서 '('를 만나면 막대기를 현재에서 한 개 더 올린다는 뜻이므로, '('를 만날 때마다 스택에 추가하고, 쇠막대기의 개수를 한 개 더한다. (7~9번째 줄)&lt;/li&gt;
&lt;li&gt;문자열을 읽으면서 ')'를 만나면 젤 위의 막대기가 끝이 났다는 뜻이다. 그러므로 스택에 추가한 '('를 한 개 뺀다. (10~11번째 줄)&lt;/li&gt;
&lt;li&gt;'.'를 만나면 (=레이저를 만나면) 현재 쌓여있는 막대기가 이등분이 되므로, 현재 스택의 길이(높이)만큼 한 번 더 더해준다. (12~13번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less56_0&quot; data-id=&quot;56_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more56_1&quot; data-id=&quot;56_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content56_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less56_1&quot; data-id=&quot;56_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def solution(arrangement):
	answer = 0
	replaced = arrangement.replace('()', '.')
	stack = list()
	
	for i, c in enumerate(replaced):
		if c == '(':
			stack.append(c)
			answer += 1
		elif c == ')':
			stack.pop()
		else:
			answer += len(stack)
	
	return answer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less56_1&quot; data-id=&quot;56_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>DP</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>큐</category>
      <category>프로그래머스</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/56</guid>
      <comments>https://empty-cloud.tistory.com/56#entry56comment</comments>
      <pubDate>Wed, 1 Jan 2020 19:34:53 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 4] Gerrit Account 구성하기</title>
      <link>https://empty-cloud.tistory.com/54</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;본 포스트는 우리가 &lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://empty-cloud.tistory.com/52&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Git&lt;/a&gt; 가이드를 완료한 상태라고 가정합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Gerrit Account&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Gerrit이란?&lt;/h3&gt;
&lt;p&gt;Gerrit은 OpenStack 커뮤니티가 사용하는 리뷰 시스템입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회원가입&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://review.opendev.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OpenStack의 Gerrit 페이지&lt;/a&gt;를 방문하고 &lt;b&gt;sign in&lt;/b&gt; 링크를 클릭합니다.&lt;/li&gt;
&lt;li&gt;사용자 이름을 선택하라는 메시지가 나타날 것입니다. StoryBoard나 Launchpad에서 사용했던 것과 같은 이름으로 사용합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;사용자 이름을 신중하게 입력하세요. 한 번 설정하면 변경할 수 없습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;지금부터 Gerrit에 로그인하면 StoryBoard나 Launchpad 로그인 정보를 입력하라는 메시지가 나타날 것입니다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개인 기여자 라이선스 계약 (Individual Contributor License Agreement)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;이것은 개인 또는 기업의 기여로부터 인정된 지적 재산권을 명확히 하기 위한 계약입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Gerrit의 설정에서 New Contributor Agreement 주소를 클릭하고, 계약에 서명하세요. 코드와 문서를 contribute 하기 위해선 이 과정이 필요합니다. 이 과정 없이는 Gerrit에 패치를 푸시할 수 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;651&quot; height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjcWmK/btqAN3gnp3r/2Ua2OHK8ULy8iqwrdxaaE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjcWmK/btqAN3gnp3r/2Ua2OHK8ULy8iqwrdxaaE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjcWmK/btqAN3gnp3r/2Ua2OHK8ULy8iqwrdxaaE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjcWmK%2FbtqAN3gnp3r%2F2Ua2OHK8ULy8iqwrdxaaE0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;651&quot; height=&quot;334&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SSH 키 설정하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;요약하자면, 우리는 SSH 키 페어를 생성하고 Gerrit 서버에 공개 키를 제공할 것입니다. 시스템이 개인 키를 소유하고 있으면 시도-응답 인증(challenge-response authentication) 도중 Gerrit에 응답하는 데 문제가 없을 것입니다.&lt;/p&gt;
&lt;p&gt;어떤 사람들은 여러 시스템에 접근하기 위해서 하나의 SSH 키 페어를 사용하는 반면에, 다른 사람들은 별도의 키 페어를 사용하는 것을 선호합니다. 두 가지 선택사항 모두 이 섹션에서 다룰 예정입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;존재하는 SSH 키 확인하기&lt;/h3&gt;
&lt;p&gt;터미널을 열고 다음을 입력합니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;ls&amp;nbsp;-la&amp;nbsp;~/.ssh&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;일반적으로 공개 키 파일 이름은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;id_dsa.pub&lt;/li&gt;
&lt;li&gt;id_ecdsa.pub&lt;/li&gt;
&lt;li&gt;id_ed25519.pub&lt;/li&gt;
&lt;li&gt;id_rsa.pub&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;만약 .pub 파일이 없거나 OpenStack Gerrt에 대해 특정 집합을 생성하려면 키를 생성해야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SSH 키 페어 생성하기&lt;/h3&gt;
&lt;p&gt;터미널에서 다음을 입력하여 주어진 이메일을 라벨로 사용하여 새 SSH 키 페어를 생성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;ssh-keygen&amp;nbsp;-t&amp;nbsp;rsa&amp;nbsp;-b&amp;nbsp;4096&amp;nbsp;-C&amp;nbsp;&quot;your_email@example.com&quot;&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&quot;Enter a file in which to save the key&quot; 메시지가 나타나면 엔터를 누르세요. 이것은 기본 위치를 허용합니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Enter&amp;nbsp;a&amp;nbsp;file&amp;nbsp;in&amp;nbsp;which&amp;nbsp;to&amp;nbsp;save&amp;nbsp;the&amp;nbsp;key&amp;nbsp;(/Users/you/.ssh/id_rsa):&amp;nbsp;[Press&amp;nbsp;enter]&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;프롬프트에서 만약 passphrase가 필요하다면 입력하고, 필요 없으면 엔터를 누르세요. (전 passphrase를 사용하지 않습니다.)&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Enter&amp;nbsp;passphrase&amp;nbsp;(empty&amp;nbsp;for&amp;nbsp;no&amp;nbsp;passphrase):&amp;nbsp;[Type&amp;nbsp;a&amp;nbsp;passphrase]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Enter&amp;nbsp;same&amp;nbsp;passphrase&amp;nbsp;again:&amp;nbsp;[Type&amp;nbsp;passphrase&amp;nbsp;again]&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OpenStack Gerrit 전용 개별 키 생성하기 (optional)&lt;/h3&gt;
&lt;p&gt;터미널에서 다음을 입력하여 주어진 이메일을 라벨로 사용하여 새 SSH 키 페어를 생성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;ssh-keygen&amp;nbsp;-t&amp;nbsp;rsa&amp;nbsp;-b&amp;nbsp;4096&amp;nbsp;-C&amp;nbsp;&quot;your_email@example.com&quot;&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&quot;Enter a file in which to save the key&quot; 메시지가 나타나면 반드시 새로운 키 페어의 이름을 지정하고 엔터를 누르세요.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Enter&amp;nbsp;a&amp;nbsp;file&amp;nbsp;in&amp;nbsp;which&amp;nbsp;to&amp;nbsp;save&amp;nbsp;the&amp;nbsp;key&amp;nbsp;(/Users/you/.ssh/id_rsa):&amp;nbsp;/Users/you/.ssh/id_openstack_rsa&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프롬프트에서 만약 passphrase가 필요하다면 입력하고, 필요 없으면 엔터를 누르세요. (전 passphrase를 사용하지 않습니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0px; padding: 0px; border: none; background-color: #272727; border-radius: 4px; height: 38px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 38px;&quot;&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f; height: 38px; width: 9px;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0px; text-align: left; height: 38px; width: 532px;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Enter&amp;nbsp;passphrase&amp;nbsp;(empty&amp;nbsp;for&amp;nbsp;no&amp;nbsp;passphrase):&amp;nbsp;[Type&amp;nbsp;a&amp;nbsp;passphrase]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Enter&amp;nbsp;same&amp;nbsp;passphrase&amp;nbsp;again:&amp;nbsp;[Type&amp;nbsp;passphrase&amp;nbsp;again]&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0px 2px 4px 0px; height: 38px; width: 12px;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;마지막으로 SSH키를 연결할 호스트가 무엇인지 구분해야 합니다. 편집기에서 &quot;~/.ssh/config/&quot;을 열고, 만약 파일이 없다면 파일을 생성하고 다음과 같은 내용을 추가하세요.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;Host&amp;nbsp;review.opendev.org&amp;nbsp;review&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Hostname&amp;nbsp;review.opendev.org&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Port&amp;nbsp;29418&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;User&amp;nbsp;&amp;lt;your_gerrit_username&amp;gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;IdentityFile&amp;nbsp;~/.ssh/id_openstack_rsa&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공개키 복사하기&lt;/h3&gt;
&lt;p&gt;터미널에서 다음을 입력하세요.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;cat&amp;nbsp;~/.ssh/id_rsa.pub&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;만약 개별 키 페어를 생성했고, 위의 예제와 같은 예제 파일 이름을 사용했다면 다음을 입력하세요.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;cat&amp;nbsp;~/.ssh/id_openstack_rsa.pub&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;결과를 클립보드에 복사하세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Gerrit으로 공개키 Import 하기&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://review.opendev.org/#/settings/ssh-keys&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Gerrit의 SSH 공개키 설정&lt;/a&gt; 페이지로 이동하세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Add Key&lt;/b&gt; 버튼을 클릭하세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Add SSH Public Key&lt;/b&gt; 텍스트 박스 안에 공개키를 붙여 넣기 하고 &lt;b&gt;Add&lt;/b&gt; 버튼을 클릭하세요.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Git Review&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Git Review란?&lt;/h3&gt;
&lt;p&gt;Git review는 OpenStack 커뮤니티에 의해 유지되는 툴입니다. 다음과 같은 하위 명령을 'git'에 추가합니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;git&amp;nbsp;review&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;OpenStack 프로젝트 레포지토리에 우리가 변경한 내용이 있는 경우, 이 하위 명령을 사용해서 변경 내용을 Gerrit에 게시하여 리뷰어들이 검토할 수 있게 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치&lt;/h3&gt;
&lt;p&gt;Debian, Ubuntu 또는 Mint와 같은 리눅스 배포를 사용하는 경우 터미널에 다음을 입력합니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;sudo&amp;nbsp;apt&amp;nbsp;install&amp;nbsp;git-review&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;RedHat, Fedora 21 또는 이전 버전, 또는 CentOS를 사용하는 경우 터미널에 다음을 입력합니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;sudo&amp;nbsp;yum&amp;nbsp;install&amp;nbsp;git-review&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Fedora 22 이상 버전을 사용하는 경우 터미널에 다음을 입력합니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;sudo&amp;nbsp;dnf&amp;nbsp;install&amp;nbsp;git-review&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구성&lt;/h3&gt;
&lt;p&gt;Git review는 사용자 이름과 Gerrit 사용자 이름이 동일하다고 가정합니다. 그렇지 않은 경우 다음 명령을 통해 설정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;git&amp;nbsp;config&amp;nbsp;--global&amp;nbsp;gitreview.username&amp;nbsp;&amp;lt;username&amp;gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;만약 Gerrit username이 뭔지 모르겠다면, &lt;a href=&quot;https://review.opendev.org/#/settings/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Gerrit settings&lt;/a&gt;를 확인하면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리뷰를 보낼 준비&lt;/h3&gt;
&lt;p&gt;우리의 패치에서 Git 커밋을 실행하기 전에 Git 리뷰를 초기화하는 것이 중요합니다. 다음 명령을 통해서 우리의 레포지토리 내의 초기 Git 리뷰 환경을 구성하세요.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;git&amp;nbsp;review&amp;nbsp;-s&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;위 명령어는 필요한 원격 호스트를 설정하고 Gerrit에 변경 사항을 푸시할 수 있도록 Git hook을 커밋합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Git review는 하나의 레포지토리 안에서 한 번만 초기화되면 됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://docs.openstack.org/contributors/common/setup-gerrit.html&quot;&gt;https://docs.openstack.org/contributors/common/setup-gerrit.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>gerrit</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/54</guid>
      <comments>https://empty-cloud.tistory.com/54#entry54comment</comments>
      <pubDate>Sun, 29 Dec 2019 03:02:02 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 3] Git (2)</title>
      <link>https://empty-cloud.tistory.com/53</link>
      <description>&lt;p&gt;본 포스트에서는 OpenStack에 contribute 할 커밋들을 작성하는 좋은 예시와 나쁜 예시를 알아볼 것입니다.&lt;/p&gt;
&lt;p&gt;공식 문서를 번역하는 것만으로도 도움이 되는 것을 느낍니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Git Commit의 좋은 관행&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개요&lt;/h3&gt;
&lt;p&gt;이 글에서 제기될 핵심과 예제들은 변경 사항을 개별적인 커밋들로 분할하는 것에 대한 가치와, 좋은 커밋 메시지들을 작성하는 중요성에 대해서 증명할 것입니다. 만약 이 가이드라인들이 광범위하게 적용된다면 OpenStack Git 기록들의 질을 향상하는 데에 엄청난 기여를 할 것입니다. 이 글은 사람들에게 여러 혜택들을 인식하게 하는 당근과 같은 반면에, Gerrit code를 리뷰하는 누구나 채찍이 될 수 있습니다.&lt;/p&gt;
&lt;p&gt;바꿔 말하면, Gerrit에서 변경사항들을 리뷰할 때, &lt;u&gt;코드의 정확성에 대해서만 간단하게 들여다보지 말라&lt;/u&gt;는 뜻입니다.&lt;/p&gt;
&lt;p&gt;즉,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커밋 메시지 자체를 리뷰하고, 커밋 메시지의 자체로 개선을 요구하세요.&lt;/li&gt;
&lt;li&gt;여러 논리적인 변화가 섞이는 커밋들을 조심하고, 커미터(commiter)에게 논리적으로 섞여있는 커밋들을 개별 커밋들로 분할하라고 요청하세요.&lt;/li&gt;
&lt;li&gt;기능적 변경사항과 함께 공백 문자의 변경사항이 섞이지 않도록 하세요.&lt;/li&gt;
&lt;li&gt;여러 기능적 변경사항들로부터 개별적으로 no-op 코드 리팩터링을 하지 마세요. (코드 리팩터링은 한 번에 하라는 뜻인 것 같습니다.)&lt;/li&gt;
&lt;li&gt;기타 등등...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;소프트웨어 소스코드는 &lt;b&gt;&quot;많이 읽히고, 드물게 작성&quot;&lt;/b&gt;됩니다. 따라서 &lt;u&gt;가장 중요한 기준은 커뮤니티 내의 커다란 개발자 그룹에 의해서 장기적인 유지보수성(maintainability)을 향상시키는 것&lt;/u&gt;이지, 코드를 두 번 다시 안 볼 수도 있는 한 명의 개발자를 위해서 희생을 하는 것이 아닙니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경사항의 구조적 분할&lt;/h3&gt;
&lt;p&gt;좋은 커밋을 만들기 위한 기본적인 규칙은 커밋당 하나의 &quot;논리적 변화&quot;만 확실하게 하는 것입니다. 이것이 중요한 규칙인 이유는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경되는 코드의 양이 적을수록 잠재적인 결함을 검토하고 식별하는 게 더 빠르고 쉽습니다.&lt;/li&gt;
&lt;li&gt;만약 변경사항이 나중에 결함으로 발견되면, 잘못된 커밋을 되돌리는 것이 필요할 수도 있습니다. 이것은 원래의 커밋과 얽혀있는, 다른 관련 없는 커밋들이 없다면 훨씬 더 쉽게 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Git의 이등분적인 성질을 사용해서 문제를 해결할 때, 잘 정의된 작은 변화는 문제가 되는 코드를 도입한 위치를 분리하는데 도움이 될 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;커밋을 작성할 때 피해야 하는 것들&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;공백 문자의 변경사항과 코드 변경사항의 혼합&lt;/b&gt;&lt;br /&gt;공백 문자의 변경은 기능적 변경사항을 모호하게 해서 리뷰어가 해당 변경이 올바른지 정확하게 판단하기 어렵게 합니다. &lt;b&gt;해결법:&lt;/b&gt; 공백 문자의 변경사항, 기능적 변경사항으로 2개의 커밋을 생성합니다. 일반적으로는 공백 문자의 변경이 먼저 이루어지지만 엄격한 규칙은 아닙니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;두 개의 관련 없는 기능적 변경사항들의 혼합&lt;/b&gt;&lt;br /&gt;다시, 만약 관련 없는 두 변경사항들이 혼합되면 리뷰어들이 문제를 식별하기 어려울 것입니다. 그리고 만약 나중에서야 잘못된 커밋을 되돌려야 한다면, 관련 없는 변경 사항들은 분리되어야 할 것이고, 이는 또 다른 버그의 위험이 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;한 개의 커밋 속 커다란 새로운 기능&lt;br /&gt;&lt;/b&gt;이는 하나의 기능 전체가 하나의 커밋으로 제공되면 안 된다는 것을 의미합니다. 새로운 기능은 종종 기존의 코드를 리팩터링 해야 합니다. 모든 리팩터링은 새로운 기능을 구현하는 작업과는 별개의 작업으로 수행하는 것이 매우 바람직합니다. 이는 리뷰어와 테스트 셋들이 리팩터링에 의해 의도하지 않은 변화가 없다는 것을 검증하는데 도움이 됩니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;잘못된 구조적 분할에 대한 예&lt;/h4&gt;
&lt;p&gt;Nova 기록에 대한 예시를 들어봅시다. 집중해주세요, 커밋 해쉬가 참조용으로 인용됐지만, 작성자 이름은 지웠습니다. 왜냐하면 어떤 사람도 비난받을 필요가 없기 때문입니다. 거의 모든 사람들이 언젠가 이런 좋은 관행들을 어긴 것에 대한 잘못이 있습니다. 게다가 이런 커밋을 리뷰하고 승인한 사람들도 이러한 커밋을 작성하고 제출한 사람만큼의 잘못이 있습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;ae878fc8b9761d099a4145617e4a48cbeb390623&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Fri&amp;nbsp;Jun&amp;nbsp;1&amp;nbsp;01:44:02&amp;nbsp;2012&amp;nbsp;+0000&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Refactor&amp;nbsp;libvirt&amp;nbsp;create&amp;nbsp;calls&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;minimizes&amp;nbsp;duplicated&amp;nbsp;code&amp;nbsp;for&amp;nbsp;create&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;makes&amp;nbsp;wait_for_destroy&amp;nbsp;happen&amp;nbsp;on&amp;nbsp;shutdown&amp;nbsp;instead&amp;nbsp;of&amp;nbsp;undefine&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;allows&amp;nbsp;for&amp;nbsp;destruction&amp;nbsp;of&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;while&amp;nbsp;leaving&amp;nbsp;the&amp;nbsp;domain&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;uses&amp;nbsp;reset&amp;nbsp;for&amp;nbsp;hard&amp;nbsp;reboot&amp;nbsp;instead&amp;nbsp;of&amp;nbsp;create/destroy&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;makes&amp;nbsp;resume_host_state&amp;nbsp;use&amp;nbsp;new&amp;nbsp;methods&amp;nbsp;instead&amp;nbsp;of&amp;nbsp;hard_reboot&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;makes&amp;nbsp;rescue/unrescue&amp;nbsp;not&amp;nbsp;use&amp;nbsp;hard&amp;nbsp;reboot&amp;nbsp;to&amp;nbsp;recreate&amp;nbsp;domain&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Change-Id:&amp;nbsp;I2072f93ad6c889d534b04009671147af653048e7&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;최소 2개의 개별적인 변경사항이 이 커밋 안에 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&quot;hard_reboot&quot; 메소드 대신 새로운 &quot;reset&quot; API의 사용 전환&lt;/li&gt;
&lt;li&gt;내부 드라이버들이 &quot;hard_reboot&quot;를 사용하지 않도록 조정&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이것과 관련한 문제는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫 번째로, 이러한 변화가 동시에 이루어져야 하는 설득력 있는 이유가 없습니다. 첫 번째 커밋은 여러 곳에서 &quot;hard_reboot&quot;를 호출하는 것을 멈추는 변경사항을 포함할 수 있었습니다. 두 번째 커밋은 &quot;hard_reboot&quot; 구현을 다시 작성할 수 있었습니다.&lt;/li&gt;
&lt;li&gt;두 번째로, libvert의 'reset' 메소드를 사용하는 변경이 대규모 코드 리팩터링에 묻히면서 리뷰어들이 더 새로운 libvirt API 버전에 의존성이 있다는 사실을 놓쳤습니다. 이 커밋이 문제가 되는 원인이라는 것이 빠르게 확인되었지만, 관련 없는 다양한 변경사항이 포함되어 있기 때문에 사소한 복구는 불가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;좋은 구조적 분할에 대한 예&lt;/h4&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;3114a97ba188895daff4a3d337b2c73855d4632d&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Mon&amp;nbsp;Jun&amp;nbsp;11&amp;nbsp;17:16:10&amp;nbsp;2012&amp;nbsp;+0100&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Update&amp;nbsp;default&amp;nbsp;policies&amp;nbsp;for&amp;nbsp;KVM&amp;nbsp;guest&amp;nbsp;PIT&amp;nbsp;&amp;amp;&amp;nbsp;RTC&amp;nbsp;timers&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;573ada525b8a7384398a8d7d5f094f343555df56&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Tue&amp;nbsp;May&amp;nbsp;1&amp;nbsp;17:09:32&amp;nbsp;2012&amp;nbsp;+0100&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Add&amp;nbsp;support&amp;nbsp;for&amp;nbsp;configuring&amp;nbsp;libvirt&amp;nbsp;VM&amp;nbsp;clock&amp;nbsp;and&amp;nbsp;timers&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;이 두 가지 변경 사항을 함께 적용하면 KVM 게스트 타이머를 구성할 수 있습니다. libvirt XML 구성을 생성하기 위한 새로운 API의 도입은 그 API를 사용하는 KVM 게스트 생성 정책의 변경 사항과 명확하게 분리되어 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;커밋 메시지 속 정보&lt;/h3&gt;
&lt;p&gt;변경 사항의 내용만큼이나 중요한 것은 그것을 설명하는 커밋 메시지의 내용입니다. 커밋 메시지를 쓸 때 기억해야 할 몇 가지 중요한 사항이 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;리뷰어가 원래 문제가 무엇인지 이해한다고 가정하지 마세요.&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리뷰어가 외부 웹 서비스/사이트에 액세스 할 수 있다고 가정하지 마세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드가 그 자체로써 증명/문서화한다고 가정하지 마세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이 변경사항이 왜 생기는지 설명하세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개선된 코드에 힌트가 있는지 커밋 메시지를 읽으세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리뷰를 결정하기에 충분한 정보가 있는지 확인하세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;첫 번째 커밋 줄이 가장 중요합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;현재 코드의 제약 사항에 대해서 설명하세요.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;따라야 할 핵심 규칙은 다음과 같습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;커밋 메시지는 패치의 정확성을 완전히 이해하고 검토하는 데 필요한 모든 정보를 포함해야 합니다. 적을수록 더 좋은 게 아닙니다. 많을수록 더 좋습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잘못된 관행에 대한 예&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시 1)&lt;/h4&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;468e64d019f51d364afb30b0eed2ad09483e0b98&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Mon&amp;nbsp;Jun&amp;nbsp;18&amp;nbsp;16:07:37&amp;nbsp;2012&amp;nbsp;-0400&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fix&amp;nbsp;missing&amp;nbsp;import&amp;nbsp;in&amp;nbsp;compute/utils.py&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fixes&amp;nbsp;bug&amp;nbsp;1014829&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;문제점:&lt;/b&gt; 이 커밋은 무엇을 import 하고, 어디가 누락이 되었으며, 왜 utils.py가 필요한 지 언급하지 않습니다. 이 정보는 실제로 버그 트래커에 있었고, 커밋 메시지 속에 복사해서 스스로 설명을 제공해야 했습니다. 예를 들면 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Add&amp;nbsp;missing&amp;nbsp;import&amp;nbsp;of&amp;nbsp;'exception'&amp;nbsp;in&amp;nbsp;compute/utils.py&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nova/compute/utils.py&amp;nbsp;makes&amp;nbsp;a&amp;nbsp;reference&amp;nbsp;to&amp;nbsp;exception.NotFound,&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;however&amp;nbsp;exception&amp;nbsp;has&amp;nbsp;not&amp;nbsp;been&amp;nbsp;imported.&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시 2)&lt;/h4&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;2020fba6731634319a0d541168fbf45138825357&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Fri&amp;nbsp;Jun&amp;nbsp;15&amp;nbsp;11:12:45&amp;nbsp;2012&amp;nbsp;-0600&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Present&amp;nbsp;correct&amp;nbsp;ec2id&amp;nbsp;format&amp;nbsp;for&amp;nbsp;volumes&amp;nbsp;and&amp;nbsp;snaps&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fixes&amp;nbsp;bug&amp;nbsp;1013765&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Add&amp;nbsp;template&amp;nbsp;argument&amp;nbsp;to&amp;nbsp;ec2utils.id_to_ec2_id()&amp;nbsp;calls&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Change-Id:&amp;nbsp;I5e574f8e60d091ef8862ad814e2c8ab993daa366&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;문제점:&lt;/b&gt; 이 커밋은 현재 잘못된 포맷이 무엇인지, 새로운 포맷은 무엇인지에 대해 언급하지 않습니다. 다시 이 정보는 버그 트래커에 있었고, 커밋 메시지에 포함되어야 했습니다. 게다가 이 버그는 이전의 커밋의 변경으로 인한 회귀 현상을 고치고 있었지만, 이전의 변화가 무엇이었는지에 대한 언급이 없습니다. 예를 들면 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Present&amp;nbsp;correct&amp;nbsp;ec2id&amp;nbsp;format&amp;nbsp;for&amp;nbsp;volumes&amp;nbsp;and&amp;nbsp;snaps&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;During&amp;nbsp;the&amp;nbsp;volume&amp;nbsp;uuid&amp;nbsp;migration,&amp;nbsp;done&amp;nbsp;by&amp;nbsp;changeset&amp;nbsp;XXXXXXX,&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ec2&amp;nbsp;id&amp;nbsp;formats&amp;nbsp;for&amp;nbsp;volumes&amp;nbsp;and&amp;nbsp;snapshots&amp;nbsp;was&amp;nbsp;dropped&amp;nbsp;and&amp;nbsp;is&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;now&amp;nbsp;using&amp;nbsp;the&amp;nbsp;default&amp;nbsp;instance&amp;nbsp;format&amp;nbsp;(i-xxxxx).&amp;nbsp;These&amp;nbsp;need&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;to&amp;nbsp;be&amp;nbsp;changed&amp;nbsp;back&amp;nbsp;to&amp;nbsp;vol-xxx&amp;nbsp;and&amp;nbsp;snap-xxxx.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Adds&amp;nbsp;a&amp;nbsp;template&amp;nbsp;argument&amp;nbsp;to&amp;nbsp;ec2utils.id_to_ec2_id()&amp;nbsp;calls&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fixes&amp;nbsp;bug&amp;nbsp;1013765&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시 3)&lt;/h4&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0px; padding: 0px; border: none; background-color: #272727; border-radius: 4px; height: 171px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 171px;&quot;&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f; height: 171px; width: 9px;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0px; text-align: left; height: 171px; width: 474px;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;f28731c1941e57b776b519783b0337e52e1484ab&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Wed&amp;nbsp;Jun&amp;nbsp;13&amp;nbsp;10:11:04&amp;nbsp;2012&amp;nbsp;-0400&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Add&amp;nbsp;libvirt&amp;nbsp;min&amp;nbsp;version&amp;nbsp;check.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fixes&amp;nbsp;LP&amp;nbsp;Bug&amp;nbsp;#1012689.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Change-Id:&amp;nbsp;I91c0b7c41804b2b25026cbe672b9210c305dc29b&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0px 2px 4px 0px; height: 171px; width: 12px;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;문제점:&lt;/b&gt; 이 커밋 메시지는 단순히 무엇이 행해졌는지 기록하고, 왜 행해졌는지는 기록하지 않습니다. 커밋 메시지는 이전의 어떤 변경 사항들이 새로운 최소 libvirt 버전을 도입했는지 언급해야 했습니다. 또, 검사에 실패했을 때 어떤 작동을 하는지 언급했어야 했습니다. 예를 들면 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Add&amp;nbsp;libvirt&amp;nbsp;version&amp;nbsp;check,&amp;nbsp;min&amp;nbsp;0.9.7&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The&amp;nbsp;commit&amp;nbsp;XXXXXXXX&amp;nbsp;introduced&amp;nbsp;use&amp;nbsp;of&amp;nbsp;the&amp;nbsp;'reset'&amp;nbsp;API&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;which&amp;nbsp;is&amp;nbsp;only&amp;nbsp;available&amp;nbsp;in&amp;nbsp;libvirt&amp;nbsp;0.9.7&amp;nbsp;or&amp;nbsp;newer.&amp;nbsp;Add&amp;nbsp;a&amp;nbsp;check&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;performed&amp;nbsp;at&amp;nbsp;startup&amp;nbsp;of&amp;nbsp;the&amp;nbsp;compute&amp;nbsp;server&amp;nbsp;against&amp;nbsp;the&amp;nbsp;libvirt&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;connection&amp;nbsp;version.&amp;nbsp;If&amp;nbsp;the&amp;nbsp;version&amp;nbsp;check&amp;nbsp;fails&amp;nbsp;the&amp;nbsp;compute&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;service&amp;nbsp;will&amp;nbsp;shutdown.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fixes&amp;nbsp;LP&amp;nbsp;Bug&amp;nbsp;#1012689.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Change-Id:&amp;nbsp;I91c0b7c41804b2b25026cbe672b9210c305dc29b&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;좋은 관행에 대한 예&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제 1)&lt;/h4&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;34&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;35&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;36&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;37&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;3114a97ba188895daff4a3d337b2c73855d4632d&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Mon&amp;nbsp;Jun&amp;nbsp;11&amp;nbsp;17:16:10&amp;nbsp;2012&amp;nbsp;+0100&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Update&amp;nbsp;default&amp;nbsp;policies&amp;nbsp;for&amp;nbsp;KVM&amp;nbsp;guest&amp;nbsp;PIT&amp;nbsp;&amp;amp;&amp;nbsp;RTC&amp;nbsp;timers&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The&amp;nbsp;default&amp;nbsp;policies&amp;nbsp;for&amp;nbsp;the&amp;nbsp;KVM&amp;nbsp;guest&amp;nbsp;PIT&amp;nbsp;and&amp;nbsp;RTC&amp;nbsp;timers&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;are&amp;nbsp;not&amp;nbsp;very&amp;nbsp;good&amp;nbsp;at&amp;nbsp;maintaining&amp;nbsp;reliable&amp;nbsp;time&amp;nbsp;in&amp;nbsp;guest&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;operating&amp;nbsp;systems.&amp;nbsp;In&amp;nbsp;particular&amp;nbsp;Windows&amp;nbsp;7&amp;nbsp;guests&amp;nbsp;will&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;often&amp;nbsp;crash&amp;nbsp;with&amp;nbsp;the&amp;nbsp;default&amp;nbsp;KVM&amp;nbsp;timer&amp;nbsp;policies,&amp;nbsp;and&amp;nbsp;old&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Linux&amp;nbsp;guests&amp;nbsp;will&amp;nbsp;have&amp;nbsp;very&amp;nbsp;bad&amp;nbsp;time&amp;nbsp;drift&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;PIT&amp;nbsp;such&amp;nbsp;that&amp;nbsp;missed&amp;nbsp;ticks&amp;nbsp;are&amp;nbsp;injected&amp;nbsp;at&amp;nbsp;the&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;normal&amp;nbsp;rate,&amp;nbsp;ie&amp;nbsp;they&amp;nbsp;are&amp;nbsp;delayed&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;RTC&amp;nbsp;such&amp;nbsp;that&amp;nbsp;missed&amp;nbsp;ticks&amp;nbsp;are&amp;nbsp;injected&amp;nbsp;at&amp;nbsp;a&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;higher&amp;nbsp;rate&amp;nbsp;to&amp;nbsp;&quot;catch&amp;nbsp;up&quot;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This&amp;nbsp;corresponds&amp;nbsp;to&amp;nbsp;the&amp;nbsp;following&amp;nbsp;libvirt&amp;nbsp;XML&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;clock&amp;nbsp;offset='utc'&amp;gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;timer&amp;nbsp;name='pit'&amp;nbsp;tickpolicy='delay'/&amp;gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;timer&amp;nbsp;name='rtc'&amp;nbsp;tickpolicy='catchup'/&amp;gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/clock&amp;gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;And&amp;nbsp;the&amp;nbsp;following&amp;nbsp;KVM&amp;nbsp;options&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-no-kvm-pit-reinjection&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-rtc&amp;nbsp;base=utc,driftfix=slew&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This&amp;nbsp;should&amp;nbsp;provide&amp;nbsp;a&amp;nbsp;default&amp;nbsp;configuration&amp;nbsp;that&amp;nbsp;works&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;acceptably&amp;nbsp;for&amp;nbsp;most&amp;nbsp;OS&amp;nbsp;types.&amp;nbsp;In&amp;nbsp;the&amp;nbsp;future&amp;nbsp;this&amp;nbsp;will&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;likely&amp;nbsp;need&amp;nbsp;to&amp;nbsp;be&amp;nbsp;made&amp;nbsp;configurable&amp;nbsp;per-guest&amp;nbsp;OS&amp;nbsp;type.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Closes-Bug:&amp;nbsp;#1011848&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Change-Id:&amp;nbsp;Iafb0e2192b5f3c05b6395ffdfa14f86a98ce3d1f&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;이 예제 커밋에 대해 눈여겨봐야 할 점들은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원래 문제가 무엇인지 설명합니다. (잘못된 KVM 기본값)&lt;/li&gt;
&lt;li&gt;적용하고자 하는 기능적 변경사항을 설명합니다. (새로운 PIT/RTC 정책)&lt;/li&gt;
&lt;li&gt;변경사항의 결과에 대해서 설명합니다. (새로운 XML/QEMU 매개변수)&lt;/li&gt;
&lt;li&gt;향후 개선의 범위를 설명합니다. (OS 유형별 구성 가능성)&lt;/li&gt;
&lt;li&gt;Closes-Bug 표기를 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제 2)&lt;/h4&gt;
&lt;p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;commit&amp;nbsp;31336b35b4604f70150d0073d77dbf63b9bf7598&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Author:&amp;nbsp;[removed]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;Date:&amp;nbsp;&amp;nbsp;&amp;nbsp;Wed&amp;nbsp;Jun&amp;nbsp;6&amp;nbsp;22:45:25&amp;nbsp;2012&amp;nbsp;-0400&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Add&amp;nbsp;CPU&amp;nbsp;arch&amp;nbsp;filter&amp;nbsp;scheduler&amp;nbsp;support&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;In&amp;nbsp;a&amp;nbsp;mixed&amp;nbsp;environment&amp;nbsp;of&amp;nbsp;running&amp;nbsp;different&amp;nbsp;CPU&amp;nbsp;architecutres,&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;one&amp;nbsp;would&amp;nbsp;not&amp;nbsp;want&amp;nbsp;to&amp;nbsp;run&amp;nbsp;an&amp;nbsp;ARM&amp;nbsp;instance&amp;nbsp;on&amp;nbsp;a&amp;nbsp;X86_64&amp;nbsp;host&amp;nbsp;and&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vice&amp;nbsp;versa.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This&amp;nbsp;scheduler&amp;nbsp;filter&amp;nbsp;option&amp;nbsp;will&amp;nbsp;prevent&amp;nbsp;instances&amp;nbsp;running&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;on&amp;nbsp;a&amp;nbsp;host&amp;nbsp;that&amp;nbsp;it&amp;nbsp;is&amp;nbsp;not&amp;nbsp;intended&amp;nbsp;for.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The&amp;nbsp;libvirt&amp;nbsp;driver&amp;nbsp;queries&amp;nbsp;the&amp;nbsp;guest&amp;nbsp;capabilities&amp;nbsp;of&amp;nbsp;the&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;host&amp;nbsp;and&amp;nbsp;stores&amp;nbsp;the&amp;nbsp;guest&amp;nbsp;arches&amp;nbsp;in&amp;nbsp;the&amp;nbsp;permitted_instances_types&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list&amp;nbsp;in&amp;nbsp;the&amp;nbsp;cpu_info&amp;nbsp;dict&amp;nbsp;of&amp;nbsp;the&amp;nbsp;host.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The&amp;nbsp;Xen&amp;nbsp;equivalent&amp;nbsp;will&amp;nbsp;be&amp;nbsp;done&amp;nbsp;later&amp;nbsp;in&amp;nbsp;another&amp;nbsp;commit.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The&amp;nbsp;arch&amp;nbsp;filter&amp;nbsp;will&amp;nbsp;compare&amp;nbsp;the&amp;nbsp;instance&amp;nbsp;arch&amp;nbsp;against&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;the&amp;nbsp;permitted_instances_types&amp;nbsp;of&amp;nbsp;a&amp;nbsp;host&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;and&amp;nbsp;filter&amp;nbsp;out&amp;nbsp;invalid&amp;nbsp;hosts.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Also&amp;nbsp;adds&amp;nbsp;ARM&amp;nbsp;as&amp;nbsp;a&amp;nbsp;valid&amp;nbsp;arch&amp;nbsp;to&amp;nbsp;the&amp;nbsp;filter.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The&amp;nbsp;ArchFilter&amp;nbsp;is&amp;nbsp;not&amp;nbsp;turned&amp;nbsp;on&amp;nbsp;by&amp;nbsp;default.&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Change-Id:&amp;nbsp;I17bd103f00c25d6006a421252c9c8dcfd2d2c49b&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 예제 커밋에 대해 눈여겨봐야 할 점들은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;문제 시나리오가 무엇인지 설명합니다. (혼합된 구조 배치)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;버그 해결에 대한 의도를 설명합니다. (구조에 대한 스케줄러 필터 만들기)&lt;/li&gt;
&lt;li&gt;버그 해결에 대한 간략한 구조를 설명합니다. (libvirt가 어떻게 구조를 반환하는지)&lt;/li&gt;
&lt;li&gt;버그 해결의 한계에 대해서 기록합니다. (Xen에 필요한 작업)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.openstack.org/wiki/GitCommitMessages&quot;&gt;https://wiki.openstack.org/wiki/GitCommitMessages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/openstack-ansible/latest/ko_KR/contributor/code-rules.html#general-guidelines-for-submitting-code&quot;&gt;https://docs.openstack.org/openstack-ansible/latest/ko_KR/contributor/code-rules.html#general-guidelines-for-submitting-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/openstack-ansible/latest/ko_KR/contributor/contribute.html&quot;&gt;https://docs.openstack.org/openstack-ansible/latest/ko_KR/contributor/contribute.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>git</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/53</guid>
      <comments>https://empty-cloud.tistory.com/53#entry53comment</comments>
      <pubDate>Sun, 29 Dec 2019 00:29:17 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 3] Git (1)</title>
      <link>https://empty-cloud.tistory.com/52</link>
      <description>&lt;p&gt;Git 관련 포스트인데 내용이 길다 보니 아마 2편 이상으로 나눠서 작성할 것 같습니다.&lt;/p&gt;
&lt;p&gt;대부분의 OpenStack 개발 도구(예: git-review)들은 Windows 환경에서 잘 돌아가지 않으니, 리눅스 환경을 기준으로 포스팅합니다.&lt;/p&gt;
&lt;p&gt;본 포스트는 Git 설치법과 OpenStack에 contribute 할 때의 커밋 메시지에 대해서 소개합니다.&lt;/p&gt;
&lt;p&gt;이것저것 알아보면서 느낀 것이지만, 아무리 공식 문서라도 프로젝트나 버전마다 권장하는 내용이 조금씩 다르니 참고 바랍니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;본 포스트는 &lt;span style=&quot;color: #006dd7;&quot;&gt;우리가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://empty-cloud.tistory.com/50&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Account Setup&lt;/a&gt; 가이드를 완료한 상태라고 가정합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Git&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Git이란?&lt;/h3&gt;
&lt;p&gt;Git은 OpenStack 커뮤니티가 소스 코드와 문서의 변경사항을 관리하기 위해 사용하는 무료 오픈 소스 분산 버전 컨트롤 시스템이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치&lt;/h3&gt;
&lt;p&gt;Debian, Ubuntu 또는 Mint 같은 리눅스 배포판들은 터미널을 열고 다음을 입력합니다.&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;sudo&amp;nbsp;apt&amp;nbsp;install&amp;nbsp;git&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Git 설정하기&lt;/h3&gt;
&lt;p&gt;깃을 설치했다면 우리는 환경을 설정할 필요가 있습니다. 터미널을 열고 다음 명령을 통해 이름, 성 그리고 이메일 주소를 입력하세요. 이것을 통해 우리의 contribution이 식별됩니다.&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;git&amp;nbsp;config&amp;nbsp;--global&amp;nbsp;user.name&amp;nbsp;&quot;Firstname&amp;nbsp;Lastname&quot;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;git&amp;nbsp;config&amp;nbsp;--global&amp;nbsp;user.email&amp;nbsp;&quot;your_email@youremail.com&quot;&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;blockquote style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a href=&quot;https://empty-cloud.tistory.com/50&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Account Setup&lt;/a&gt; 단계에서 사용한 것과 동일한 이메일을 사용하세요.&lt;/span&gt;&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Commit Message&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;커밋 메시지들은 리뷰어(reviewer)들이 가장 첫 번째로 보는 것들이고 git log 안에서 설명으로 사용됩니다. 커밋 메시지들은 레포지토리 안에서 변경 사항들의 기록에 대한 설명을 제공합니다. 커밋 메시지들은 패치(patch)가 한 번 적용이 되면 변경할 수 없습니다.&lt;/p&gt;
&lt;p&gt;형식:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요약 (Summary Line)&lt;/li&gt;
&lt;li&gt;빈 줄&lt;/li&gt;
&lt;li&gt;내용 (Body)&lt;/li&gt;
&lt;li&gt;빈 줄&lt;/li&gt;
&lt;li&gt;태그 (Tags)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약 (Summary Line)&lt;/h3&gt;
&lt;p&gt;요약은 패치 내용을 간략하게 설명합니다. 문자 제한은 50자입니다. 요약은 마침표로 끝나지 말아야 합니다. 만약 변화가 한 번의 커밋으로 끝나지 않는다면 커밋 메시지를 WIP(Work in Progress)로 시작하세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;내용 (Body)&lt;/h3&gt;
&lt;p&gt;내용은 해결하고자 하는 이슈에 대한 설명, 고쳐야 하는 이유, 설루션에 대한 설명, 코드 구조를 어떻게 개선하는지에 대한 추가적인 설명, 또는 다른 연관 있는 패치에 대한 참조 등을 포함합니다. 각 줄은 72자로 제한됩니다. 내용은 독자가 문제의 원인을 이해한다거나, 외부 사이트에 접속이 가능하다는 가정 없이, 문제와 관련하여 모든 중요한 정보를 포함하고 있어야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;태그 (Tags)&lt;/h3&gt;
&lt;p&gt;태그는 다른 도구들로 변경 사항들을 연결하는 데 사용되는 참조입니다.&lt;/p&gt;
&lt;p&gt;다음의 태그들은 필수적으로 요구됩니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Change-Id&lt;/b&gt; 줄은 변경사항을 설명하는 고유의 해쉬입니다. Change-Id는 Git commit hook에 의해서 자동적으로 생성됩니다. 이 줄은 리뷰 피드백에 따라오는 커밋을 rebase 할 때 변경되면 안 됩니다. 왜냐하면 이 줄은 패치 버전을 추적하기 위해 Gerrit에 의해 사용되기 때문입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StoryBoard 명시 태그:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Task:&lt;/b&gt; 변경사항에 의해 생성되는 StoryBoard 내의 작업 번호. 이 태그는 자동으로 그 작업을 'Review' 상태로 업데이트하고, 패치를 적용할 때 우리에게 배정됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Story:&lt;/b&gt; 패치가 적용되고자 하는 StoryBoard 내의 스토리 번호. 이 태그는 우리의 패치를 참조하는 링크와 함께 스토리에 코멘트를 달 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Launchpad 명시 태그:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Closes-Bug:&lt;/b&gt; 만약 커밋이 참조하는 버그를 완전하게 해결하고 이슈를 닫고자 한다면 &lt;b&gt;Closes-Bug&lt;/b&gt; 태그를 사용하세요. 태그 숫자로 해당 버그의 Launchpad의 ID를 사용하세요; Gerrit이 자동으로 그 버그로 링크를 생성할 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Partial-Bug:&lt;/b&gt; 만약 커밋이 버그의 부분적인 해결과 추가적인 작업이 필요하다면 &lt;b&gt;Partial-Bug&lt;/b&gt; 태그를 사용하세요. 태그 숫자로 해당 버그의 Launchpad의 ID를 사용하세요; Gerrit이 자동으로 그 버그로 링크를 생성할 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Related-Bug:&lt;/b&gt; 만약 커밋이 단순히 참조된 버그와 연관이 있다면 &lt;b&gt;Related-Bug&lt;/b&gt; 태그를 사용하세요. 태그 숫자로 해당 버그의 Launchpad의 ID를 사용하세요; Gerrit이 자동으로 그 버그로 링크를 생성할 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Partial-Implements&lt;/b&gt;&lt;b&gt;:&lt;/b&gt; 만약 커밋이 Launchpad blueprint를 부분적으로 구현한다면 &lt;b&gt;Partial-Implements&lt;/b&gt;&amp;nbsp;태그를 사용하세요. 태그 ID로써 blueprint의 이름을 사용하세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Implements:&lt;/b&gt; 만약 커밋이 Launchpad blueprint를 완전히 구현한다면 &lt;b&gt;Implements&lt;/b&gt; 태그를 사용하세요. 태그 ID로써 blueprint의 이름을 사용하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;만약 해당 프로젝트가 StoryBoard를 사용한다면 StoryBoard의 태그를 사용하고, Launchpad를 사용한다면 Launchpad의 태그를 사용하면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음의 태그들은 선택사항이지만, 패치에 적용될 수 있으면 사용하는 것이 권장됩니다.&lt;/p&gt;
&lt;p&gt;이는 포스팅하지 않으니, 아래의 주소를 참고하기 바랍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DocImpact&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;APIImpact&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SecurityImpact&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;UpgradeImpact&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Depends-On&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://docs.openstack.org/contributors/common/git.html&quot;&gt;https://docs.openstack.org/contributors/common/git.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.openstack.org/wiki/GitCommitMessages&quot;&gt;https://wiki.openstack.org/wiki/GitCommitMessages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribute</category>
      <category>git</category>
      <category>openstack</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/52</guid>
      <comments>https://empty-cloud.tistory.com/52#entry52comment</comments>
      <pubDate>Sat, 28 Dec 2019 19:12:11 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 2] Account Setup</title>
      <link>https://empty-cloud.tistory.com/50</link>
      <description>&lt;p&gt;OpenStack 커뮤니티에서 채팅 서비스로 IRC를 사용한다지만 저는 사용할 일이 없을 것 같아서 포스팅하지 않습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenStack Foundation Account 구성하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;OpenStack Foundation Account는 우리가&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선거에서 투표할 수 있게 합니다.&lt;/li&gt;
&lt;li&gt;OpenStack 프로젝트에서 특정 포지션에 지원할 수 있게 합니다.&lt;/li&gt;
&lt;li&gt;OpenStack 컨퍼런스에서 발표할 수 있게 합니다.&lt;/li&gt;
&lt;li&gt;OpenStack 컨퍼런스에서 투표할 수 있게 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(딱히 쓸 일이 없어보이는 장점들...)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회원가입&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;만약 코드 기여를 하고싶다면 반드시 같은 이메일을 사용하도록 하세요. 왜냐하면 나중에 각 계정들의 이메일 주소가 일치하는 것이 중요합니다.&lt;/i&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;a href=&quot;https://www.openstack.org/join&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OpenStack Foundation 회원가입 페이지&lt;/a&gt;로 이동하세요.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Individual Member:Free&lt;/b&gt; 섹션의 &lt;b&gt;Community Member&lt;/b&gt;를 클릭하세요.&lt;/li&gt;
&lt;li&gt;이름과 이메일 주소, 성별을 작성합니다. &lt;u&gt;회원가입의 각 단계마다 같은 이메일 주소를 사용하세요.&lt;/u&gt; 이 이메일 주소는 로그인 할 때 사용됩니다. 그리고 성별은 공공 API에 의해서 사용 가능합니다.&lt;/li&gt;
&lt;li&gt;나머지 양식을 채우고 제출하세요.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WRi3f/btqAMPJz4f3/KJKRgvbrFdaH5LtJTOkow1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WRi3f/btqAMPJz4f3/KJKRgvbrFdaH5LtJTOkow1/img.png&quot; data-alt=&quot;OpenStack 공식 문서에 있는 그림. Foundation Member말고 왼쪽의 Community Member를 선택한다. Foundation Member는 주기적으로 투표하는게 의무이며, 이를 수행하지 않을 시 계정이 정지된다고 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WRi3f/btqAMPJz4f3/KJKRgvbrFdaH5LtJTOkow1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWRi3f%2FbtqAMPJz4f3%2FKJKRgvbrFdaH5LtJTOkow1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OpenStack 공식 문서에 있는 그림. Foundation Member말고 왼쪽의 Community Member를 선택한다. Foundation Member는 주기적으로 투표하는게 의무이며, 이를 수행하지 않을 시 계정이 정지된다고 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Task Tracker Account 구성하기&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;OpenStack 커뮤니티는 현재 버그 추적 소프트웨어로 Launchpad에서 StoryBoard로 변경하는 과정 중에 있습니다. 프로젝트가 명시된 on-boarding 문서에서 그 프로젝트가 Launchpad를 쓰는지 StoryBoard를 쓰는지 특별히 주의하세요. 만약 당신의 프로젝트가 Launchpad를 사용하고 있다면, 이 포스트(문서)의 Launchpad 섹션을 주목하세요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Task Tracker Account는 우리가&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버그를 제보할 수 있게 합니다.&lt;/li&gt;
&lt;li&gt;새로운 기능을 위한 스토리를 생성할 수 있게 합니다. (프로세스는 프로젝트마다 다릅니다.)&lt;/li&gt;
&lt;li&gt;버그/새로운 기능의 진행결과를 추적할 수 있게 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;StoryBoard&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;StoryBoard란?&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://storyboard.openstack.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;StoryBoard&lt;/a&gt;는 OpenStack 커뮤니티가 개발하고 있는 버그 추적 소프트웨어이고, 현재 &lt;a href=&quot;https://superuser.openstack.org/articles/openstack-gerrit-storyboard-integration/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;마이그레이션&lt;/a&gt; 작업 중입니다. &lt;a href=&quot;https://storyboard.openstack.org/#!/project/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;몇몇 프로젝트&lt;/a&gt;는 이미 StoryBoard를 사용하고 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회원가입&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://storyboard.openstack.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;storyboard.openstack.org&lt;/a&gt;로 이동하세요.&lt;/li&gt;
&lt;li&gt;오른쪽 위에 &lt;b&gt;login&lt;/b&gt; 버튼을 클릭하세요.&lt;/li&gt;
&lt;li&gt;이미 Ubuntu One 계정을 소유하고 있다면, 그냥 로그인하면 됩니다.&lt;/li&gt;
&lt;li&gt;만약 Ubuntu One 계정이 없다면, &lt;b&gt;I am a new Ubuntu One user&lt;/b&gt;를 클릭하세요.&lt;/li&gt;
&lt;li&gt;양식을 채우고 제출하세요.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;417&quot; height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8Pa5R/btqAM38FU65/X6VwzwyYq7vkAoRtgSWJd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8Pa5R/btqAM38FU65/X6VwzwyYq7vkAoRtgSWJd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8Pa5R/btqAM38FU65/X6VwzwyYq7vkAoRtgSWJd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8Pa5R%2FbtqAM38FU65%2FX6VwzwyYq7vkAoRtgSWJd0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;417&quot; height=&quot;501&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Launchpad&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Launchpad란?&lt;/h4&gt;
&lt;p&gt;Launchpad는 OpenStack 커뮤니티가 버그 추적을 하는 구식(오래된) 방법입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회원가입&lt;/h4&gt;
&lt;p&gt;이미 회원가입을 했습니다. Launchpad는 StoryBoard처럼 인증을 위해 Ubuntu One 계정을 사용합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://docs.openstack.org/contributors/common/accounts.html&quot;&gt;https://docs.openstack.org/contributors/common/accounts.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribution</category>
      <category>launchpad</category>
      <category>openstack</category>
      <category>storyboard</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/50</guid>
      <comments>https://empty-cloud.tistory.com/50#entry50comment</comments>
      <pubDate>Sat, 28 Dec 2019 04:31:36 +0900</pubDate>
    </item>
    <item>
      <title>[OpenStack에 contribute하기 - 1] 개요</title>
      <link>https://empty-cloud.tistory.com/49</link>
      <description>&lt;p&gt;개인적으로 OpenStack의 프로젝트에 기여하는 Developer가 돼보고 싶어서 시작하는 프로젝트입니다.&lt;/p&gt;
&lt;p&gt;공식 문서를 참고해 차근차근 진행해 볼 계획이니, 프로젝트의 진행 속도는 많이 느릴 것 같습니다. (핑계 +1)&lt;/p&gt;
&lt;p&gt;공식 문서가 OpenStack의&amp;nbsp;버전 별로 매번 업데이트 되기 때문에, 이것 저것 찾아보고, 번역하면서 포스팅하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenStack이란?&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Software&lt;/h3&gt;
&lt;p&gt;OpenStack은 기업과 통신회사를 포함한 다양한 사용 사례들을 다루는 사설 및 공인 클라우드 플랫폼을 제공하는 소프트웨어 패키지입니다. 주요 초점은 IaaS(Infrastructure as a Service)와 IaaS위에서 빌드된 추가적인 서비스들입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;소프트웨어로써, OpenStack은 실제 다른 구조로 결합될 수 있는 마이크로서비스들의 집합으로부터 만들어졌습니다. 그 마이크로서비스들은 사용자들을 위해 REST API를 제공합니다. 그 사용자들은 클라우드 운영자(Operator)가 될 수도 있고 다른 서비스가 될 수도 있습니다. API를 더 쉽게 사용하기 위해 SDK를 사용하는 것도 가능합니다. 이 SDK들 또한 OpenStack 커뮤니티 내에서 프로젝트로 개발되고 있습니다.&lt;/p&gt;
&lt;p&gt;커뮤니티에 의해서 개발된 서비스들은 소스코드로부터 설치할 tar파일로 이용 가능하고, 또한 다른 리눅스 배포에서 사용 가능하게 하거나 OpenStack 배포의 일부로 개선되고 패키징됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OpenStack 프로젝트의 구조&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GrppU/btqAKhOebGa/QbVNc2Ym8bdd4C013p0Fvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GrppU/btqAKhOebGa/QbVNc2Ym8bdd4C013p0Fvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GrppU/btqAKhOebGa/QbVNc2Ym8bdd4C013p0Fvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGrppU%2FbtqAKhOebGa%2FQbVNc2Ym8bdd4C013p0Fvk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Contribution이란?&lt;/h3&gt;
&lt;p&gt;오픈 소스 프로젝트에서 contribution이란, 그 프로젝트가 목적을 달성하도록 돕는 어떤 것이든 될 수 있습니다. 코드 기여뿐만 아니라 테스팅, 문서화, 요구사항 수집, 버그 리포팅 등이 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스트는 다음 주소를 참고하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://docs.openstack.org/contributors/common/introduction.html&quot;&gt;https://docs.openstack.org/contributors/common/introduction.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Cloud Computing/Openstack</category>
      <category>contribution</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/49</guid>
      <comments>https://empty-cloud.tistory.com/49#entry49comment</comments>
      <pubDate>Sat, 28 Dec 2019 01:38:59 +0900</pubDate>
    </item>
    <item>
      <title># 1</title>
      <link>https://empty-cloud.tistory.com/48</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;IMG_4219.jpg&quot; data-origin-width=&quot;5989&quot; data-origin-height=&quot;3993&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uuacx/btqARXOH7id/ooR1XmRlvV5rmuklf1M1I1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uuacx/btqARXOH7id/ooR1XmRlvV5rmuklf1M1I1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uuacx/btqARXOH7id/ooR1XmRlvV5rmuklf1M1I1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUuacx%2FbtqARXOH7id%2FooR1XmRlvV5rmuklf1M1I1%2Fimg.jpg&quot; data-filename=&quot;IMG_4219.jpg&quot; data-origin-width=&quot;5989&quot; data-origin-height=&quot;3993&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;각자의 방향으로&lt;/p&gt;</description>
      <category>나만의 사진전</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/48</guid>
      <comments>https://empty-cloud.tistory.com/48#entry48comment</comments>
      <pubDate>Fri, 27 Dec 2019 18:50:28 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 다리를 지나는 트럭</title>
      <link>https://empty-cloud.tistory.com/47</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42583&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tJDWL/btqAJhnlKOH/JrRHbvgJSdYvN7PZpumxuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tJDWL/btqAJhnlKOH/JrRHbvgJSdYvN7PZpumxuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tJDWL/btqAJhnlKOH/JrRHbvgJSdYvN7PZpumxuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtJDWL%2FbtqAJhnlKOH%2FJrRHbvgJSdYvN7PZpumxuk%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;335&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more47_0&quot; data-id=&quot;47_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content47_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less47_0&quot; data-id=&quot;47_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;스택/큐&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;쉬운 문제인 줄 알았는데, 자꾸 한 가지 생각에 꽂히다 보니 문제를 푸는데 시간이 걸렸다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;다리 위를 지나고 있는 트럭에 대해, 다리 위에서 소요한 시간을 센다. (나의 경우 다리 길이에서부터 1씩 감소시켰다.) (12~14번째 줄)&lt;/li&gt;
&lt;li&gt;만약 다리 위를 지나고 있는 트럭 중 가장 첫 번째 트럭이 다리의 길이만큼 시간을 소모했으면, 다리를 통과시킨다. (16~19번째줄)&lt;/li&gt;
&lt;li&gt;만약 대기하고 있는 트럭이 있고, 다리를 지나갈 공간이 있으면 트럭을 출발시킨다. (21~27번째 줄)&lt;/li&gt;
&lt;li&gt;소요된 시간을 센다. (28번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다리 위를 지나고 있는 트럭부터 계산을 하고 대기하고 있는 트럭을 신경써야 했지만, 나는 대기하고 있는 트럭부터 신경을 써서 출발시키려다보니 문제가 더 복잡해졌다.&lt;/p&gt;
&lt;p&gt;간단한 문제인데 쓸 데 없이 한 가지 생각에 붙잡혀 있다보니 아까운 시간만 날렸다..&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less47_0&quot; data-id=&quot;47_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more47_1&quot; data-id=&quot;47_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content47_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less47_1&quot; data-id=&quot;47_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;collections&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;deque&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;def&lt;/span&gt;&amp;nbsp;solution(bridge_length,&amp;nbsp;weight_limit,&amp;nbsp;truck_weights):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;waiting&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque(truck_weights)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;passing&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bridge_weight&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;waiting&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;or&lt;/span&gt;&amp;nbsp;passing:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;count&amp;nbsp;time&amp;nbsp;for&amp;nbsp;the&amp;nbsp;trucks&amp;nbsp;on&amp;nbsp;the&amp;nbsp;bridge&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #4be6fa;&quot;&gt;len&lt;/span&gt;(passing)):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;passing[i][&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;the&amp;nbsp;first&amp;nbsp;truck&amp;nbsp;on&amp;nbsp;the&amp;nbsp;bridge&amp;nbsp;is&amp;nbsp;about&amp;nbsp;to&amp;nbsp;pass&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;passing&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;passing[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;][&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;weight,&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;passing.popleft()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bridge_weight&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;weight&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;there's&amp;nbsp;any&amp;nbsp;waiting&amp;nbsp;truck&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;waiting:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;the&amp;nbsp;bridge&amp;nbsp;is&amp;nbsp;available&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;len&lt;/span&gt;(passing)&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;bridge_length&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;bridge_weight&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;waiting[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;weight_limit:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;weight&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;waiting.popleft()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;passing.append([weight,&amp;nbsp;bridge_length])&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bridge_weight&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;weight&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;return&lt;/span&gt;&amp;nbsp;answer&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less47_1&quot; data-id=&quot;47_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>덱</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>큐</category>
      <category>프로그래머스</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/47</guid>
      <comments>https://empty-cloud.tistory.com/47#entry47comment</comments>
      <pubDate>Fri, 27 Dec 2019 18:24:58 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17779] 게리맨더링 2</title>
      <link>https://empty-cloud.tistory.com/45</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17779&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBQTNs/btqAIQXCDhY/R141KYM98YwT7ROq8fCU1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBQTNs/btqAIQXCDhY/R141KYM98YwT7ROq8fCU1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBQTNs/btqAIQXCDhY/R141KYM98YwT7ROq8fCU1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBQTNs%2FbtqAIQXCDhY%2FR141KYM98YwT7ROq8fCU1K%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more45_0&quot; data-id=&quot;45_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content45_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less45_0&quot; data-id=&quot;45_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;브루트 포스&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;모든 경우의 수를 따져서 문제에 조건에 해당하는 최적의 결과를 찾아야 하는 게 목적이다.&lt;/p&gt;
&lt;p&gt;모든 경우의 수를 따질 대상은 &lt;u&gt;기준점이 되는 &lt;b&gt;(x, y)&lt;/b&gt;와 &lt;b&gt;d1&lt;/b&gt;, &lt;b&gt;d2&lt;/b&gt;&lt;/u&gt;이다. (81~84번째 줄)&lt;/p&gt;
&lt;p&gt;그리고 각 경우가 유효한 경우인지는 다음과 같이 문제에 명시되어 있으므로 이를 적용해서 필터링한다. (85번째 줄)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처2.PNG&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mUNFg/btqAK4NsWcS/VOoPCjEHLIwLckXolIqP1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mUNFg/btqAK4NsWcS/VOoPCjEHLIwLckXolIqP1K/img.png&quot; data-alt=&quot;문제에 명시된 선거구를 나누는 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mUNFg/btqAK4NsWcS/VOoPCjEHLIwLckXolIqP1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmUNFg%2FbtqAK4NsWcS%2FVOoPCjEHLIwLckXolIqP1K%2Fimg.png&quot; data-filename=&quot;캡처2.PNG&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;413&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;문제에 명시된 선거구를 나누는 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;맨 처음 문제를 풀 때 다음과 같은 로직으로 문제를 해결하려고 했다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;5번 선거구의 경계를 구한다.&lt;/li&gt;
&lt;li&gt;5번 선거구에 포함된 인구를 구한다.&lt;/li&gt;
&lt;li&gt;1, 2, 3, 4번 선거구에 포함된 인구를 구한다.&lt;/li&gt;
&lt;li&gt;인구가 가장 많은 선거구와 가장 적은 선거구의 차이가 최소가 되는 경우를 찾는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그런데 2번 과정에서 5번 선거구에 포함된 인구를 구할 방법이 떠오르지 않았다.&lt;/p&gt;
&lt;p&gt;문제를 계속해서 고민하던 도중 다음과 같은 생각이 떠올랐다.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;문제에 1번~4번 선거구에 해당하는 조건이 명시되어 있으니, 차라리 &lt;u&gt;1번~4번 선거구의 인구를 먼저 구하고, 전체 인구에서 각 선거구의 인구를 빼면 5번 선거구의 인구를 구할 수 있겠다!&lt;/u&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새로운 2차원 배열(temp_board)에 &lt;u&gt;5번 선거구의 경계를 구하고, 이를 표시&lt;/u&gt;한다. (13~29번째 줄)&lt;/li&gt;
&lt;li&gt;1번에서 표시해놓은 &lt;u&gt;5번 선거구의 경계를 사용하여 1번~4번 선거구에 포함된 인구를 구한다&lt;/u&gt;. 그리고 각 선거구의 인원을 구할 때, 최대 선거구 인원과 최소 선거구 인원을 갱신한다. (31~69번째 줄)&lt;/li&gt;
&lt;li&gt;전체 인구에서 1번~4번 선거구의 인원을 빼서 5번 선거구의 인원을 구한다. 그리고 최대 선거구 인원과 최소 선거구 인원을 갱신한다. (71~74번째 줄)&lt;/li&gt;
&lt;li&gt;최대 선거구 인원과 최소 선거구 인원의 차를 구한다. (76번째 줄)&lt;/li&gt;
&lt;li&gt;모든 경우의 수에 대해서 1번~4번 과정을 반복하여 최대 선거구 인원과 최소 선거구 인원의 차가 최소가 되는 정답을 찾는다. (81~86번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2번에서 말한 5번 선거구의 경계를 사용했다는 말은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;863&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjIp0v/btqAJhN16TH/oWuUjkmz7Loat9PNIUScaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjIp0v/btqAJhN16TH/oWuUjkmz7Loat9PNIUScaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjIp0v/btqAJhN16TH/oWuUjkmz7Loat9PNIUScaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjIp0v%2FbtqAJhN16TH%2FoWuUjkmz7Loat9PNIUScaK%2Fimg.png&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;863&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;각 선거구를 탐색하는 순서는 원 안에 표시된 순서와 같다.&lt;/p&gt;
&lt;p&gt;5번 선거구의 경계를 만나면 바로 다음 행의 탐색으로 넘어간다. (지금 생각해보니 2번, 4번 선거구의 행을 순회할 때 굳이 밑에서부터 올라갈 필요가 없다... 위에서 아래로 탐색하는 게 더 이해하기 편할 것 같다.)&lt;/p&gt;
&lt;p&gt;위와 같이 1번~4번 선거구의 인구를 먼저 구하면 복잡하게 5번 선거구의 인구를 고려할 필요가 없어지게 된다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less45_0&quot; data-id=&quot;45_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more45_1&quot; data-id=&quot;45_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content45_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less45_1&quot; data-id=&quot;45_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;34&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;35&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;36&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;37&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;38&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;39&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;40&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;41&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;42&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;43&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;44&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;45&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;46&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;47&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;48&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;49&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;50&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;51&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;52&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;53&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;54&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;55&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;56&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;57&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;58&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;59&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;60&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;61&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;62&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;63&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;64&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;65&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;66&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;67&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;68&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;69&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;70&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;71&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;72&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;73&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;74&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;75&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;76&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;77&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;78&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;79&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;80&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;81&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;82&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;83&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;84&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;85&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;86&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;87&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;88&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;sys&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;(sys.stdin.readline())&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;A&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;list(map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split()))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;line[c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;def&lt;/span&gt;&amp;nbsp;solution(x,&amp;nbsp;y,&amp;nbsp;d1,&amp;nbsp;d2):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_sum,&amp;nbsp;min_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;sys.maxsize&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;border&amp;nbsp;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board[x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d][y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;d]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;border&amp;nbsp;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board[x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d][y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;border&amp;nbsp;3&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board[x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d][y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;border&amp;nbsp;4&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board[x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d][y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;d]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;sector&amp;nbsp;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d1):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;temp_board[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;A[i][j]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_sum,&amp;nbsp;sum1)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(min_sum,&amp;nbsp;sum1)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;sector&amp;nbsp;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n,&amp;nbsp;y,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;temp_board[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;A[i][j]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_sum,&amp;nbsp;sum2)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(min_sum,&amp;nbsp;sum2)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;sector&amp;nbsp;3&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum3&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d1,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;temp_board[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum3&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;A[i][j]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_sum,&amp;nbsp;sum3)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(min_sum,&amp;nbsp;sum3)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;sector&amp;nbsp;4&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum4&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n,&amp;nbsp;x&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n,&amp;nbsp;y&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;temp_board[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum4&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;A[i][j]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_sum,&amp;nbsp;sum4)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(min_sum,&amp;nbsp;sum4)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;sector&amp;nbsp;5&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sum5&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;total&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;(sum1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;sum2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;sum3&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;sum4)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_sum,&amp;nbsp;sum5)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(min_sum,&amp;nbsp;sum5)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;return&lt;/span&gt;&amp;nbsp;max_sum&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;min_sum&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;total&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;sum(map(sum,&amp;nbsp;A))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;total&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;d1&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;d2&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;n:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(answer,&amp;nbsp;solution(r,&amp;nbsp;c,&amp;nbsp;d1,&amp;nbsp;d2))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(answer)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less45_1&quot; data-id=&quot;45_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>브루트포스</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/45</guid>
      <comments>https://empty-cloud.tistory.com/45#entry45comment</comments>
      <pubDate>Thu, 26 Dec 2019 21:14:25 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17142] 연구소 3</title>
      <link>https://empty-cloud.tistory.com/44</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17142&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw00nT/btqADHSJwhp/8e8lhZlVuS7cNRD3PpQqOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw00nT/btqADHSJwhp/8e8lhZlVuS7cNRD3PpQqOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw00nT/btqADHSJwhp/8e8lhZlVuS7cNRD3PpQqOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw00nT%2FbtqADHSJwhp%2F8e8lhZlVuS7cNRD3PpQqOK%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;73&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more44_0&quot; data-id=&quot;44_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content44_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less44_0&quot; data-id=&quot;44_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;이 문제는 &lt;b&gt;DFS, BFS&lt;/b&gt; 문제이다. (DFS로는 안 풀어도 된다.)&lt;/p&gt;
&lt;p&gt;연구소 내의 모든 바이러스 중에서 m개의 바이러스를 선택하는 과정을 DFS로 풀면 DFS 문제가 되겠지만, 나는 itertools 모듈의 combinations 함수를 사용하였다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;입력으로부터 연구소 내의 빈 방의 개수와 바이러스의 위치를 저장한다. (9~17번째 줄)&lt;/li&gt;
&lt;li&gt;모든 바이러스 중에서 m개의 바이러스를 선택하는 모든 경우의 수를 구한다. (20~21번째 줄)&lt;/li&gt;
&lt;li&gt;2번에서 구한 m개의 바이러스를 큐에 삽입한다. (22~26번째 줄)&lt;/li&gt;
&lt;li&gt;3번에서 큐에 삽입한 m개의 바이러스를 BFS를 통해 확산시킨다. (확산될 수 있는 경우의 수는 빈 방일 경우와 비활성 바이러스일 경우 확산될 수 있다. &lt;u&gt;빈 방의 경우에만 감염된 방의 개수와 소요시간을 업데이트한다.)&lt;/u&gt; (28~43번째 줄)&lt;/li&gt;
&lt;li&gt;1번의 BFS를 통해 연구소 내 모든 방에 바이러스가 퍼졌다면, 최소 시간을 업데이트한다. (44~46번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less44_0&quot; data-id=&quot;44_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more44_1&quot; data-id=&quot;44_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content44_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less44_1&quot; data-id=&quot;44_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;34&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;35&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;36&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;37&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;38&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;39&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;40&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;41&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;42&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;43&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;44&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;45&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;46&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;47&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;48&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;49&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;50&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;51&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;52&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;53&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;54&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;sys&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;collections&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;deque&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;itertools&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;combinations&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;n,&amp;nbsp;m&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split())&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;board&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[list(map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split()))&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;directions&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;((&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;),&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;),&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;),&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;get&amp;nbsp;list&amp;nbsp;of&amp;nbsp;viruses&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;virus_list&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;empty_rooms&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(n):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;empty_rooms&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;elif&lt;/span&gt;&amp;nbsp;board[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virus_list.appendleft((i,&amp;nbsp;j))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;sys.maxsize&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;for&amp;nbsp;all&amp;nbsp;combinations&amp;nbsp;of&amp;nbsp;viruses&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;selected&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;combinations(virus_list,&amp;nbsp;m):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;visited&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;set()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;virus&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;selected:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q.appendleft((virus,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;visited.add(virus)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;bfs&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;infected,&amp;nbsp;max_dist&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;q:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cur,&amp;nbsp;dist&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;q.pop()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;dr,&amp;nbsp;dc&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;directions:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;cur[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;dr&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;cur[&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;dc&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;next_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;n&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;next_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;n:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;(next_r,&amp;nbsp;next_c)&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;not&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;visited:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[next_r][next_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;update&amp;nbsp;distance&amp;nbsp;and&amp;nbsp;infection&amp;nbsp;count&amp;nbsp;only&amp;nbsp;if&amp;nbsp;virus&amp;nbsp;is&amp;nbsp;spread&amp;nbsp;in&amp;nbsp;empty&amp;nbsp;room&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[next_r][next_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;infected&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_dist&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_dist,&amp;nbsp;dist&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q.appendleft(((next_r,&amp;nbsp;next_c),&amp;nbsp;dist&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;visited.add((next_r,&amp;nbsp;next_c))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;update&amp;nbsp;answer&amp;nbsp;if&amp;nbsp;we&amp;nbsp;succeeded&amp;nbsp;in&amp;nbsp;spreading&amp;nbsp;virus&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;infected&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;empty_rooms:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;min(answer,&amp;nbsp;max_dist)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;answer&amp;nbsp;is&amp;nbsp;not&amp;nbsp;found&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;sys.maxsize&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;answer&amp;nbsp;is&amp;nbsp;found&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;else&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(answer)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less44_1&quot; data-id=&quot;44_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>bfs</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/44</guid>
      <comments>https://empty-cloud.tistory.com/44#entry44comment</comments>
      <pubDate>Sun, 22 Dec 2019 23:47:28 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17140] 이차원 배열과 연산</title>
      <link>https://empty-cloud.tistory.com/43</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sCgbE/btqAB3WCS4S/8xizm5KKEAByIvpqP3i1TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sCgbE/btqAB3WCS4S/8xizm5KKEAByIvpqP3i1TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sCgbE/btqAB3WCS4S/8xizm5KKEAByIvpqP3i1TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsCgbE%2FbtqAB3WCS4S%2F8xizm5KKEAByIvpqP3i1TK%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;73&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more43_0&quot; data-id=&quot;43_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content43_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less43_0&quot; data-id=&quot;43_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;시뮬레이션&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;처음에 문제를 읽자마자 든 생각은 두 가지였다.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;collections 모듈의 Counter 자료구조를 사용해야겠다.&lt;/li&gt;
&lt;li&gt;행과 열에 대한 연산이 있으므로, 열에 대한 연산은 A 행렬을 transpose 시켜야겠다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 두 가지 생각을 잘 구현하니 AC를 받았다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;행렬 A를 초기 상태의 3 * 3 행렬로 초기화한다. (5~9번째 줄)&lt;/li&gt;
&lt;li&gt;R연산) A의 각 행마다 &lt;b&gt;(숫자, 숫자가 나타난 횟수)&lt;/b&gt;의 리스트를 생성하고, 그 리스트에 대해&amp;nbsp;&lt;u&gt;&lt;b&gt;(&lt;/b&gt;&lt;/u&gt;&lt;b&gt;숫자가 나타난 횟수, 숫자)&lt;/b&gt; 순으로 오름차순으로 정렬한다. (17번째 줄)&lt;/li&gt;
&lt;li&gt;R연산) 정렬된 0이 아닌 숫자들을 해당하는 A의 행에 새롭게 대입시킨다. (19~24번째 줄)&lt;/li&gt;
&lt;li&gt;R연산을 통해 바뀐 열의 최대 길이를 갱신하고, 나머지 칸들은 0으로 지정한다. (25~28번째 줄)&lt;/li&gt;
&lt;li&gt;C연산) A의 전치 행렬을 구한다. (31~32번째 줄)&lt;/li&gt;
&lt;li&gt;C연산) A의 전치 행렬의 각 행마다 &lt;b&gt;(숫자, 숫자가 나타난 횟수)&lt;/b&gt;의 리스트를 생성하고, 그 리스트에 대해 &lt;u&gt;&lt;b&gt;(&lt;/b&gt;&lt;/u&gt;&lt;b&gt;숫자가 나타난 횟수, 숫자)&lt;/b&gt; 순으로 오름차순으로 정렬한다. (&lt;u&gt;A의 전치 행렬의 각 행에 대해 실행한 연산 == A의 각 열에 대해 실행한 연산&lt;/u&gt;) (34번째 줄)&lt;/li&gt;
&lt;li&gt;C연산) 정렬된 0이 아닌 숫자들을 해당하는 A의 열에 새롭게 대입시킨다. (36~41번째 줄)&lt;/li&gt;
&lt;li&gt;C연산을 통해 바뀐 열의 최대 길이를 갱신하고, 나머지 칸들은 0으로 지정한다. (42~45번째 줄)&lt;/li&gt;
&lt;li&gt;정답을 찾거나, 연산 횟수가 100번을 넘어갈 때까지 1~8번을 반복한다. (12번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사용하면 할수록 느끼는 거지만, collections 모듈의 Counter 자료구조와 zip 함수는 매우 유용한 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less43_0&quot; data-id=&quot;43_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more43_1&quot; data-id=&quot;43_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content43_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less43_1&quot; data-id=&quot;43_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;34&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;35&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;36&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;37&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;38&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;39&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;40&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;41&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;42&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;43&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;44&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;45&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;46&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;47&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;48&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;49&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;50&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;51&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;52&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;sys&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;collections&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;Counter&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;r,&amp;nbsp;c,&amp;nbsp;k&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().strip().split())&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;A&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;101&lt;/span&gt;)]&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;101&lt;/span&gt;)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;list(map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().strip().split()))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;line[j]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;answer,&amp;nbsp;max_r,&amp;nbsp;max_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;A[r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;k&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;101&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;operation&amp;nbsp;R&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;max_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max_c:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;for&amp;nbsp;all&amp;nbsp;rows&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(max_r):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sorted_row&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;list(sorted(Counter(A[i]).items(),&amp;nbsp;key&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;lambda&amp;nbsp;x:&amp;nbsp;(x[&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;],&amp;nbsp;x[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;])))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;key,&amp;nbsp;occurrence&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;sorted_row:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;key&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;key&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i][j&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;occurrence&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_c,&amp;nbsp;j)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;set&amp;nbsp;rest&amp;nbsp;of&amp;nbsp;blanks&amp;nbsp;to&amp;nbsp;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(j,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;101&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;operation&amp;nbsp;C&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;else&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;transposed&amp;nbsp;matrix&amp;nbsp;of&amp;nbsp;A&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transposed_A&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;list(zip(&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;*&lt;/span&gt;A))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(max_c):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sorted_col&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;list(sorted(Counter(transposed_A[j]).items(),&amp;nbsp;key&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;lambda&amp;nbsp;x:&amp;nbsp;(x[&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;],&amp;nbsp;x[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;])))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;key,&amp;nbsp;occurrence&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;sorted_col:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;key&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;key&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;occurrence&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;max(max_r,&amp;nbsp;i)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;set&amp;nbsp;rest&amp;nbsp;of&amp;nbsp;blanks&amp;nbsp;to&amp;nbsp;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(i,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;101&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A[i][j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;101&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(answer)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;else&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less43_1&quot; data-id=&quot;43_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>시뮬레이션</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/43</guid>
      <comments>https://empty-cloud.tistory.com/43#entry43comment</comments>
      <pubDate>Sat, 21 Dec 2019 22:23:46 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17143] 낚시왕</title>
      <link>https://empty-cloud.tistory.com/42</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17143&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;65&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cF9tbr/btqAv1SfY5H/BzZ9SqpVxvkqVPxHQuF8C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cF9tbr/btqAv1SfY5H/BzZ9SqpVxvkqVPxHQuF8C1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cF9tbr/btqAv1SfY5H/BzZ9SqpVxvkqVPxHQuF8C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcF9tbr%2FbtqAv1SfY5H%2FBzZ9SqpVxvkqVPxHQuF8C1%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;65&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more42_0&quot; data-id=&quot;42_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content42_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less42_0&quot; data-id=&quot;42_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;시뮬레이션&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;생각보다 쉬워보였는데 문제를 해결하는데 하루 2시간씩 총 3일이 걸렸다. (정말 바보같았다.)&lt;/p&gt;
&lt;p&gt;처음에는 객체지향적으로 상어 클래스를 만들고 상어들의 배열을 만들어서 선형적인 시간복잡도로 문제를 해결하려고 했지만, 딱히 그럴 필요가 없을 것 같아서 그냥 2차원 배열의 각 원소들에게 상어의 정보를 할당하였다.&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;2차원 배열에 상어에 대한 정보를 저장한다. (30~33번째 줄)&lt;/li&gt;
&lt;li&gt;어부를 이동시킨다. (38~39번째 줄)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;낚시왕이 있는 열에 있는 상어 중에서 땅과 제일 가까운 상어를 잡는다. 상어를 잡으면 격자판에서 잡은 상어가 사라진다. (40~45번째 줄)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;상어가 이동한다. (&lt;u&gt;각 상어가 이동할 때마다 이동한 상어의 정보를 새로운 2차원 배열에 저장한다.&lt;/u&gt;) (47~58번째 줄)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;새로운 2차원 배열을 기준으로 2번~4번 작업을 반복해서 실행한다. (59번째 줄)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;위 로직중 &lt;span style=&quot;color: #333333;&quot;&gt;내가 실수했던 부분이자, &lt;/span&gt;가장 신경써야 할 부분은 상어를 이동시키는 부분이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;상어를 이동시킬 때, 최대 이동속도가 1000이므로 이를 최소화하고자 하였다. (6~10번째 줄)&lt;/p&gt;
&lt;p&gt;결론적으로 &lt;u&gt;상어가 벽에 부딪혀 원래의 위치로 돌아오기까지는 &lt;b&gt;속도 % (2 * 벽의 길이) - 2&lt;/b&gt;&lt;/u&gt;로 계산해야 했지만, 나는 &lt;b&gt;속도 % (2 * 벽의 길이) - 1&lt;/b&gt;로 계산을 했었다.&lt;/p&gt;
&lt;p&gt;이 문제를 해결하는데 시간이 오래 걸렸던 이유는, 테스트케이스는 물론 질문게시판에 있는 모든 반례가 다 통과되었기 때문에 어느 부분이 문제였는지 애초부터 몰랐던 것이다.&lt;/p&gt;
&lt;p&gt;다음부터는 모듈러 연산을 사용할 때 조금 더 주의깊게 살펴봐야겠다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less42_0&quot; data-id=&quot;42_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more42_1&quot; data-id=&quot;42_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content42_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less42_1&quot; data-id=&quot;42_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;34&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;35&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;36&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;37&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;38&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;39&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;40&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;41&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;42&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;43&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;44&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;45&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;46&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;47&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;48&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;49&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;50&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;51&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;52&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;53&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;54&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;55&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;56&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;57&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;58&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;59&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;60&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;61&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;sys&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;def&lt;/span&gt;&amp;nbsp;move(r,&amp;nbsp;c,&amp;nbsp;s,&amp;nbsp;d,&amp;nbsp;z):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_speed&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;s&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;minimize&amp;nbsp;the&amp;nbsp;steps&amp;nbsp;of&amp;nbsp;shark's&amp;nbsp;movement&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;or&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_speed&amp;nbsp;%&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;*&lt;/span&gt;&amp;nbsp;R)&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;elif&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;or&lt;/span&gt;&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;4&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_speed&amp;nbsp;%&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;*&lt;/span&gt;&amp;nbsp;C)&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_r,&amp;nbsp;new_c,&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;r,&amp;nbsp;c,&amp;nbsp;d&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(temp_speed):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;new_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;elif&lt;/span&gt;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;new_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;R:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;elif&lt;/span&gt;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;new_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;C:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;4&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;elif&lt;/span&gt;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;new_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_d&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;directions[new_d][&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;directions[new_d][&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;return&lt;/span&gt;&amp;nbsp;new_r,&amp;nbsp;new_c,&amp;nbsp;s,&amp;nbsp;new_d,&amp;nbsp;z&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;R,&amp;nbsp;C,&amp;nbsp;M&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split())&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;board&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(M):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r,&amp;nbsp;c,&amp;nbsp;s,&amp;nbsp;d,&amp;nbsp;z&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split())&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[s,&amp;nbsp;d,&amp;nbsp;z]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;directions&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;{&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&amp;nbsp;(&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;),&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;:&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;),&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;3&lt;/span&gt;:&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;),&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;4&lt;/span&gt;:&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)}&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;1.&amp;nbsp;move&amp;nbsp;fisher&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;fisher_pos&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;2.&amp;nbsp;get&amp;nbsp;the&amp;nbsp;nearest&amp;nbsp;shark&amp;nbsp;from&amp;nbsp;the&amp;nbsp;ground&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[r][fisher_pos]:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r][fisher_pos][&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][fisher_pos]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;3.&amp;nbsp;move&amp;nbsp;sharks&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[r][c]:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_r,&amp;nbsp;new_c,&amp;nbsp;s,&amp;nbsp;d,&amp;nbsp;z&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;move(r,&amp;nbsp;c,&amp;nbsp;board[r][c][&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;],&amp;nbsp;board[r][c][&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;],&amp;nbsp;board[r][c][&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;])&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;sharks&amp;nbsp;conflict&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;temp_board[new_r][new_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board[new_r][new_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[s,&amp;nbsp;d,&amp;nbsp;z]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;elif&lt;/span&gt;&amp;nbsp;z&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;temp_board[new_r][new_c][&lt;span style=&quot;color: #c10aff;&quot;&gt;2&lt;/span&gt;]:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;temp_board[new_r][new_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[s,&amp;nbsp;d,&amp;nbsp;z]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;temp_board&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(answer)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less42_1&quot; data-id=&quot;42_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>시뮬레이션</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/42</guid>
      <comments>https://empty-cloud.tistory.com/42#entry42comment</comments>
      <pubDate>Thu, 19 Dec 2019 16:31:51 +0900</pubDate>
    </item>
    <item>
      <title>[백준 17144] 미세먼지 안녕!</title>
      <link>https://empty-cloud.tistory.com/41</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17144&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dg0Yl7/btqAs2JGQ2z/Kj9Cf0IQwYtWH5TJRNDR40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dg0Yl7/btqAs2JGQ2z/Kj9Cf0IQwYtWH5TJRNDR40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dg0Yl7/btqAs2JGQ2z/Kj9Cf0IQwYtWH5TJRNDR40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdg0Yl7%2FbtqAs2JGQ2z%2FKj9Cf0IQwYtWH5TJRNDR40%2Fimg.png&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;74&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more41_0&quot; data-id=&quot;41_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content41_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less41_0&quot; data-id=&quot;41_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;이 문제는 &lt;b&gt;시뮬레이션&lt;/b&gt; 문제이다.&lt;/p&gt;
&lt;p&gt;처음에 문제를 훑고 나서 BFS 문제라고 생각했지만, 자세하게 문제를 읽어보니 &lt;a href=&quot;https://empty-cloud.tistory.com/3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;나무 재테크&lt;/a&gt;와 비슷한 문제였다.&lt;/p&gt;
&lt;p&gt;문제를 풀 때 주의할 점은 &lt;u&gt;먼지를 확산시킬 때, 먼지를 확산시킬 칸들의 정보를 저장해두었다가, 모든 칸의 먼지의 양을 줄이고 나서 확산시켜야 한다.&lt;/u&gt; (이는 나무 재테크 문제에서처럼 똑같이 적용되는데, 각 칸을 순회할 때 먼지를 확산시켜 먼지의 양을 주변 칸에 더해버리면 다음 칸에서 확산시킬 먼지의 양에 영향을 끼친다.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;공기청정기의 위치를 찾는다. (8~12번째 줄)&lt;/li&gt;
&lt;li&gt;각 칸에서 미세먼지를 확산시킬 인접한 칸들을 찾고, 그만큼 현재 칸의 미세먼지의 양을 줄인다.&lt;br /&gt;동시에 인접한 칸들의 위치를 큐에 저장한다. (18~32번째 줄)&lt;/li&gt;
&lt;li&gt;큐에 저장된 칸에 미세먼지를 확산시킨다. (34~37번째 줄)&lt;/li&gt;
&lt;li&gt;공기청정기를 반 시계방향으로 작동시킨다. (39~51번째 줄)&lt;/li&gt;
&lt;li&gt;공기청정기를 시계방향으로 작동시킨다. (53~65번째 줄)&lt;/li&gt;
&lt;li&gt;주어진 시간 동안 1번부터 5번까지의 작업을 반복한다. (16번째 줄)&lt;/li&gt;
&lt;li&gt;미세먼지의 총합을 구한다. (67~71번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less41_0&quot; data-id=&quot;41_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more41_1&quot; data-id=&quot;41_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content41_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less41_1&quot; data-id=&quot;41_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;34&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;35&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;36&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;37&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;38&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;39&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;40&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;41&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;42&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;43&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;44&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;45&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;46&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;47&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;48&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;49&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;50&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;51&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;52&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;53&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;54&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;55&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;56&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;57&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;58&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;59&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;60&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;61&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;62&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;63&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;64&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;65&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;66&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;67&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;68&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;69&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;70&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;71&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;72&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;73&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;sys&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;collections&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;deque&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;R,&amp;nbsp;C,&amp;nbsp;T&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split())&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;board&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[list(map(&lt;span style=&quot;color: #4be6fa;&quot;&gt;int&lt;/span&gt;,&amp;nbsp;sys.stdin.readline().split()))&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;_&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R)]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;air_purifier&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;list()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;find&amp;nbsp;air&amp;nbsp;purifier&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;air_purifier.append((r,&amp;nbsp;c))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;for&amp;nbsp;a&amp;nbsp;given&amp;nbsp;time&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;directions&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;((&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;),&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;),&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;),&amp;nbsp;(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;t&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(T):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spread_q&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;for&amp;nbsp;all&amp;nbsp;dust&amp;nbsp;on&amp;nbsp;the&amp;nbsp;map&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spread_amount&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;/&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;5&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;for&amp;nbsp;all&amp;nbsp;directions&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;dr,&amp;nbsp;dc&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;directions:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;dr&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;dc&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;next&amp;nbsp;block&amp;nbsp;is&amp;nbsp;available&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;next_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;R&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;next_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;C:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[next_r][next_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;spread_amount&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spread_q.appendleft((next_r,&amp;nbsp;next_c,&amp;nbsp;spread_amount))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;spread&amp;nbsp;dust&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;spread_q:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r,&amp;nbsp;c,&amp;nbsp;spread_amount&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;spread_q.pop()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;spread_amount&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;air&amp;nbsp;purifier&amp;nbsp;works&amp;nbsp;counter-clockwise&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base_r,&amp;nbsp;base_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;air_purifier[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(base_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][base_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][base_c]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(base_r):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;base_c,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[base_r][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[base_r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;else&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[base_r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[base_r][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;air&amp;nbsp;purifier&amp;nbsp;works&amp;nbsp;clockwise&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base_r,&amp;nbsp;base_c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;air_purifier[&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(base_r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][base_c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][base_c]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;base_r,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[r][C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;][C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;base_c,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[base_r][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[base_r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;else&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;board[base_r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[base_r][c&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;r&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(R):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;c&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(C):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;board[r][c]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;board[r][c]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #4be6fa;&quot;&gt;print&lt;/span&gt;(answer)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less41_1&quot; data-id=&quot;41_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>시뮬레이션</category>
      <category>알고리즘</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/41</guid>
      <comments>https://empty-cloud.tistory.com/41#entry41comment</comments>
      <pubDate>Sat, 14 Dec 2019 21:45:17 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 탑</title>
      <link>https://empty-cloud.tistory.com/39</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42588&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1.PNG&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p7DgR/btqzFeYbHpf/KCRtqNQgX5k5PEW8VUKIr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p7DgR/btqzFeYbHpf/KCRtqNQgX5k5PEW8VUKIr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p7DgR/btqzFeYbHpf/KCRtqNQgX5k5PEW8VUKIr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp7DgR%2FbtqzFeYbHpf%2FKCRtqNQgX5k5PEW8VUKIr1%2Fimg.png&quot; data-filename=&quot;1.PNG&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more39_0&quot; data-id=&quot;39_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content39_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less39_0&quot; data-id=&quot;39_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는&amp;nbsp;&lt;b&gt;스택/큐&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 탑은 왼쪽으로 레이저 신호를 발사하므로, 각 탑에 대해서 왼쪽에 위치한 모든 탑에 대해 탐색을 진행한다. (4~7번째 줄)&lt;/li&gt;
&lt;li&gt;만약 현재 탑에서 왼쪽에 위치한 탑들 중에 높이가 높은 탑이 있다면, 그 탑의 위치를 기록한다. (8~11번째 줄)&lt;/li&gt;
&lt;li&gt;만약 왼쪽에 위치한 탑들 중에 높이가 높은 탑이 없다면 0을 기록한다. (12~14번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less39_0&quot; data-id=&quot;39_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more39_1&quot; data-id=&quot;39_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content39_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less39_1&quot; data-id=&quot;39_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;def&lt;/span&gt;&amp;nbsp;solution(heights):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i,&amp;nbsp;height&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;enumerate(heights):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;found&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;False&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;for&amp;nbsp;all&amp;nbsp;front&amp;nbsp;towers&amp;nbsp;from&amp;nbsp;the&amp;nbsp;nearest&amp;nbsp;tower&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;j&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #4be6fa;&quot;&gt;range&lt;/span&gt;(i&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;heights[j]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;height:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer.append(j&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;found&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;True&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;there's&amp;nbsp;no&amp;nbsp;higher&amp;nbsp;tower&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;not&lt;/span&gt;&amp;nbsp;found:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer.append(&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;return&lt;/span&gt;&amp;nbsp;answer&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less39_1&quot; data-id=&quot;39_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>큐</category>
      <category>프로그래머스</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/39</guid>
      <comments>https://empty-cloud.tistory.com/39#entry39comment</comments>
      <pubDate>Sun, 10 Nov 2019 22:54:20 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 프린터</title>
      <link>https://empty-cloud.tistory.com/38</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42587&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1.PNG&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k4KXL/btqzFWvWLi9/Ojmgk79KN0Bjs0kNLz44FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k4KXL/btqzFWvWLi9/Ojmgk79KN0Bjs0kNLz44FK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k4KXL/btqzFWvWLi9/Ojmgk79KN0Bjs0kNLz44FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk4KXL%2FbtqzFWvWLi9%2FOjmgk79KN0Bjs0kNLz44FK%2Fimg.png&quot; data-filename=&quot;1.PNG&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more38_0&quot; data-id=&quot;38_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content38_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less38_0&quot; data-id=&quot;38_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;스택/큐&lt;/b&gt; 문제이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제를 읽다보면 처음에 중요도가 더 높은 문서를 인쇄해야한다고 해서, 우선순위 큐를 생각했었지만, 입력값의 범위가 100보다 작다고 명시되어 있어서 그냥 n^2의 복잡도로 문제를 풀었다.&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;빠른 삽입과 제거를 위해 주어진 대기목록의 list형 변수를 deque로 변환한다. (7~10번째 줄)&lt;/li&gt;
&lt;li&gt;대기 목록의 가장 앞에 있는 문서를 꺼내고, 대기 목록 중에 우선순위가 더 높은 문서가 있는지 확인한다. (13~21번째 줄)&lt;/li&gt;
&lt;li&gt;만약 대기 목록 중, 우선순위가 더 높은 문서가 있다면 대기 목록의 맨 뒤에 현재 문서를 추가한다. (17~21번째 줄)&lt;/li&gt;
&lt;li&gt;만약 문서가 추가되었다면, 1번으로 되돌아간다. (23~25번째 줄)&lt;/li&gt;
&lt;li&gt;만약 문서가 출력되었다면, 횟수를 센다. (26~27번째 줄)&lt;/li&gt;
&lt;li&gt;5번에서 출력한 문서가 찾고자 하던 문서라면 종료한다. (29~31번째 줄)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여담으로, 7~10번째 줄을 다음과 같이 줄일 수 있다는 것을 다른 사람의 코드를 보고 깨달았다.&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;make&amp;nbsp;deque&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;q&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque([(idx,&amp;nbsp;priority)&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;idx,&amp;nbsp;priority&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;enumerate(priorities)])&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less38_0&quot; data-id=&quot;38_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more38_1&quot; data-id=&quot;38_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content38_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less38_1&quot; data-id=&quot;38_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;29&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;30&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;31&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;32&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;33&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;collections&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;deque&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;def&lt;/span&gt;&amp;nbsp;solution(priorities,&amp;nbsp;location):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;make&amp;nbsp;deque&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;idx,&amp;nbsp;priority&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;enumerate(priorities):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q.append((idx,&amp;nbsp;priority))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;q:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;job_idx,&amp;nbsp;job_priority&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;q.popleft()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delayed&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;False&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;idx,&amp;nbsp;priority&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;q:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;current&amp;nbsp;job&amp;nbsp;is&amp;nbsp;delayed&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;job_priority&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;priority:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q.append((job_idx,&amp;nbsp;job_priority))&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delayed&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;True&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;don't&amp;nbsp;count&amp;nbsp;if&amp;nbsp;the&amp;nbsp;job&amp;nbsp;is&amp;nbsp;delayed&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;delayed:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;add&amp;nbsp;count&amp;nbsp;printed&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;found&amp;nbsp;the&amp;nbsp;job&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;job_idx&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;location:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;return&lt;/span&gt;&amp;nbsp;answer&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less38_1&quot; data-id=&quot;38_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>덱</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>큐</category>
      <category>프로그래머스</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/38</guid>
      <comments>https://empty-cloud.tistory.com/38#entry38comment</comments>
      <pubDate>Sun, 10 Nov 2019 21:52:11 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 기능개발</title>
      <link>https://empty-cloud.tistory.com/37</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42586&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;b&gt;문제 보기&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1.PNG&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pdWu0/btqzFzOsEx8/DVJRe0rIhMjtXUp4DOH2kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pdWu0/btqzFzOsEx8/DVJRe0rIhMjtXUp4DOH2kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pdWu0/btqzFzOsEx8/DVJRe0rIhMjtXUp4DOH2kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpdWu0%2FbtqzFzOsEx8%2FDVJRe0rIhMjtXUp4DOH2kk%2Fimg.png&quot; data-filename=&quot;1.PNG&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more37_0&quot; data-id=&quot;37_0&quot;&gt;풀이&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content37_0&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less37_0&quot; data-id=&quot;37_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;이 문제는 &lt;b&gt;스택/큐&lt;/b&gt; 문제이다. (난 덱(deque)을 사용해서 문제를 풀었다..)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;문제를 푼 로직은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;progress와 speed 리스트를 deque 자료형으로 변환한다. (7~8번째 줄)&lt;/li&gt;
&lt;li&gt;각 진행속도만큼 progress를 증가시킨다. (12~14번째 줄)&lt;/li&gt;
&lt;li&gt;만약 맨 첫 번째 작업이 끝이 나면, 연속된 작업 중 완료된 작업들의 개수를 구한다. (16~22번째 줄)&lt;/li&gt;
&lt;li&gt;만약 배포된 작업이 있으면 정답 배열에 추가한다. (24~26번째 줄)&lt;/li&gt;
&lt;li&gt;작업이 남아있는 동안 2~4번을 반복해서 실행한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less37_0&quot; data-id=&quot;37_0&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;풀이&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;button type=&quot;button&quot; class=&quot;btn_more&quot; id=&quot;more37_1&quot; data-id=&quot;37_1&quot;&gt;코드&lt;/button&gt;&lt;div class=&quot;moreless_content&quot; id=&quot;content37_1&quot; style=&quot;display: none;&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less37_1&quot; data-id=&quot;37_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;
  &lt;p class=&quot;txt_view&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;colorscripter-code&quot; style=&quot;color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position: relative !important; overflow: auto;&quot;&gt;
&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin: 0; padding: 0; border: none; background-color: #272727; border-radius: 4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 6px; border-right: 2px solid #4f4f4f;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; word-break: normal; text-align: right; color: #aaa; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;1&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;2&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;3&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;4&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;5&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;6&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;7&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;8&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;9&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;10&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;11&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;12&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;13&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;14&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;15&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;16&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;17&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;18&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;19&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;20&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;21&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;22&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;23&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;24&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;25&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;26&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;27&lt;/div&gt;
&lt;div style=&quot;line-height: 130%;&quot;&gt;28&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;padding: 6px 0; text-align: left;&quot;&gt;
&lt;div style=&quot;margin: 0; padding: 0; color: #f0f0f0; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; line-height: 130%;&quot;&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;from&lt;/span&gt;&amp;nbsp;collections&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;import&lt;/span&gt;&amp;nbsp;deque&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;def&lt;/span&gt;&amp;nbsp;solution(progresses,&amp;nbsp;speeds):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;[]&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque(progresses)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;speeds&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;deque(speeds)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;q:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;make&amp;nbsp;progress&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;for&lt;/span&gt;&amp;nbsp;i,&amp;nbsp;speed&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;in&lt;/span&gt;&amp;nbsp;enumerate(speeds):&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q[i]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;speed&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;the&amp;nbsp;first&amp;nbsp;job&amp;nbsp;can&amp;nbsp;be&amp;nbsp;released&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;q[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;100&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;release&amp;nbsp;and&amp;nbsp;count&amp;nbsp;progresses&amp;nbsp;continuously&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;while&lt;/span&gt;&amp;nbsp;q&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;and&lt;/span&gt;&amp;nbsp;q[&lt;span style=&quot;color: #c10aff;&quot;&gt;0&lt;/span&gt;]&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;100&lt;/span&gt;:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q.popleft()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;speeds.popleft()&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count&amp;nbsp;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #0086b3;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff3399;&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #c10aff;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #999999;&quot;&gt;#&amp;nbsp;if&amp;nbsp;there's&amp;nbsp;a&amp;nbsp;released&amp;nbsp;progress&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;if&lt;/span&gt;&amp;nbsp;count:&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer.append(count)&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;padding: 0 6px; white-space: pre; line-height: 130%;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ff3399;&quot;&gt;return&lt;/span&gt;&amp;nbsp;answer&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: -13px; margin-right: 5px; font-size: 9px; font-style: italic;&quot;&gt;&lt;a style=&quot;color: #4f4f4ftext-decoration:none;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Colored by Color Scripter&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td style=&quot;vertical-align: bottom; padding: 0 2px 4px 0;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: white;&quot; href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-size: 9px; word-break: normal; background-color: #4f4f4f; color: white; border-radius: 10px; padding: 1px;&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;btn_less&quot; id=&quot;less37_1&quot; data-id=&quot;37_1&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;코드&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>덱</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>큐</category>
      <category>프로그래머스</category>
      <author>최성훈</author>
      <guid isPermaLink="true">https://empty-cloud.tistory.com/37</guid>
      <comments>https://empty-cloud.tistory.com/37#entry37comment</comments>
      <pubDate>Sun, 10 Nov 2019 19:44:39 +0900</pubDate>
    </item>
  </channel>
</rss>