<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>susukkang.LOG</title>
    <link>https://steady-record.tistory.com/</link>
    <description>나는 밤하늘의 디벨로퍼</description>
    <language>ko</language>
    <pubDate>Wed, 8 Apr 2026 04:29:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>developer of the night sky</managingEditor>
    <image>
      <title>susukkang.LOG</title>
      <url>https://tistory1.daumcdn.net/tistory/6632775/attach/121c4746e896477aafaf5602807ef554</url>
      <link>https://steady-record.tistory.com</link>
    </image>
    <item>
      <title>[컴퓨터/IT] 객체지향의 사실과 오해 2</title>
      <link>https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4-2</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;이전글 이어서 : &lt;a href=&quot;https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1743320839408&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[컴퓨터/IT] 객체지향의 사실과 오해&quot; data-og-description=&quot;[참고 블로그]https://techblog.woowahan.com/2502/&amp;nbsp;&amp;nbsp;1장 협력하는 객체들의 공동체 ■ 역할, 책임, 협력시스템은 역할과 책임을 수행하는 객체로 분할되고, 시스템의 기능은 객체 간의 연쇄적인 요청과 &quot; data-og-host=&quot;steady-record.tistory.com&quot; data-og-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4&quot; data-og-url=&quot;https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ESRkc/hyYvf6dwys/2OufMFQ7qFe9L08sjk37GK/img.jpg?width=300&amp;amp;height=411&amp;amp;face=0_0_300_411,https://scrap.kakaocdn.net/dn/cWUwon/hyYxRDj1j9/rG8Suxe2jIWLSnvDMgLHm1/img.jpg?width=300&amp;amp;height=411&amp;amp;face=0_0_300_411,https://scrap.kakaocdn.net/dn/EGanX/hyYvlL6s00/ywbAMaQTkjGSr7dcVQCAE1/img.png?width=1280&amp;amp;height=1096&amp;amp;face=210_168_312_686&quot;&gt;&lt;a href=&quot;https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ESRkc/hyYvf6dwys/2OufMFQ7qFe9L08sjk37GK/img.jpg?width=300&amp;amp;height=411&amp;amp;face=0_0_300_411,https://scrap.kakaocdn.net/dn/cWUwon/hyYxRDj1j9/rG8Suxe2jIWLSnvDMgLHm1/img.jpg?width=300&amp;amp;height=411&amp;amp;face=0_0_300_411,https://scrap.kakaocdn.net/dn/EGanX/hyYvlL6s00/ywbAMaQTkjGSr7dcVQCAE1/img.png?width=1280&amp;amp;height=1096&amp;amp;face=210_168_312_686');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[컴퓨터/IT] 객체지향의 사실과 오해&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[참고 블로그]https://techblog.woowahan.com/2502/&amp;nbsp;&amp;nbsp;1장 협력하는 객체들의 공동체 ■ 역할, 책임, 협력시스템은 역할과 책임을 수행하는 객체로 분할되고, 시스템의 기능은 객체 간의 연쇄적인 요청과&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;steady-record.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;04장: 역할, 책임, 협력&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 책임&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 책임의 분류&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 책임은 &amp;lsquo;객체가 무엇을 알고 있는가(knowing)&amp;rsquo;와 &amp;lsquo;무엇을 할 수 있는가(doing)&amp;rsquo;로 구성된다.&lt;/li&gt;
&lt;li&gt;하는 것(doing)
&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;/li&gt;
&lt;li&gt;아는 것(knowing)
&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;/li&gt;
&lt;li&gt;책임은 객체지향 설계의 품질을 결정하는 중요한 요소이며 명확히 정의해야 한다.&lt;/li&gt;
&lt;li&gt;책임은 객체의 공용 인터페이스를 구성한다.&lt;/li&gt;
&lt;li&gt;일반적으로 객체지향의 책임은 외부에서 접근 가능한 공용 서비스 관점에서 논의된다.&lt;/li&gt;
&lt;li&gt;즉, 책임은 객체가 외부에 제공할 수 있는 정보(아는 것)와 외부에서 제공할 수 있는 서비스(하는 것)의 목록이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;커피숍에서 바리스타 객체는 커피를 만든다(doing), 사용 가능한 원두 종류를 알고 있다(knowing)라는 책임을 가진다.&lt;/li&gt;
&lt;li&gt;고객 객체는 커피를 주문한다(doing), 메뉴에서 선택할 수 있는 항목을 알고 있다(knowing)라는 책임을 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 책임과 메시지&lt;/span&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;/li&gt;
&lt;li&gt;책임은 객체가 협력에 참여하기 위해 수행해야 하는 행위를 상위 수준에서 개략적으로 서술한 것이다.&lt;/li&gt;
&lt;li&gt;책임을 결정한 후 실제 협력을 정제하면서 이를 메시지로 변환할 때, 하나의 책임이 여러 개의 메시지로 분할될 수 있다.&lt;/li&gt;
&lt;li&gt;객체지향 설계는 협력에 참여하는 객체가 수행할 책임과 메시지를 주고받을 객체를 결정하는 것으로부터 시작된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 역할&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 책임의 집합이 의미하는 것&lt;/span&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;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 역할이 답이다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;협력 안에서 역할은 &quot;이 자리를 해당 역할을 수행할 수 있는 어떤 객체라도 대신할 수 있습니다.&quot;라는 의미를 갖는다.&lt;/li&gt;
&lt;li&gt;동일한 역할을 수행할 수 있다는 것은 동일한 책임의 집합을 수행할 수 있다는 뜻이다.&lt;/li&gt;
&lt;li&gt;역할은 유사한 협력을 추상화하여 인지 부담을 줄이고 재사용성을 높인다.&lt;/li&gt;
&lt;li&gt;역할은 객체지향 설계의 단순성(simplicity), 유연성(flexibility), 재사용성(reusability)을 지원하는 개념이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;li&gt;바리스타 객체는 커피를 만든다는 역할을 수행하고, 캐셔 객체는 주문을 받는다는 역할을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;3. 협력의 추상화&lt;/span&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;/li&gt;
&lt;li&gt;구체적인 객체 대신 추상적인 역할을 사용하면 동일한 협력 구조를 다양한 문맥에서 재사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;4. 대체 가능성&lt;/span&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;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 객체의 모양을 결정하는 협력&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;협력을 따라 흐르는 객체의 책임&lt;/span&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;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;/li&gt;
&lt;li&gt;객체에 책임을 할당하면, 이 책임은 객체가 외부에 제공할 행동이 된다.&lt;/li&gt;
&lt;li&gt;행동을 결정한 후, 해당 행동을 수행하는 데 필요한 데이터를 고민해야 한다.&lt;/li&gt;
&lt;li&gt;데이터와 행동이 어느 정도 결정된 후, 클래스의 구현 방법을 선택한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&amp;nbsp;객체지향 설계 기법&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 책임-주도 설계 (Responsibility-Driven Design, RDD)&lt;/span&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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&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;사용자에게 제공해야 하는 기능(시스템 책임)을 파악한다.&lt;/li&gt;
&lt;li&gt;시스템 책임을 더 작은 책임으로 분할한다.&lt;/li&gt;
&lt;li&gt;분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.&lt;/li&gt;
&lt;li&gt;객체가 책임을 수행하는 과정에서 다른 객체의 도움이 필요한 경우, 이를 책임질 적절한 객체 또는 역할을 찾는다.&lt;/li&gt;
&lt;li&gt;해당 객체/역할에게 책임을 할당하여 협력이 이루어지도록 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 디자인 패턴 (Design Patterns)&lt;/span&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;/li&gt;
&lt;li&gt;공통으로 사용할 수 있는 역할, 책임, 협력의 템플릿을 제공하여 설계를 효율적으로 수행할 수 있도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;3. 테스트 주도 개발 (Test-Driven Development, TDD)&lt;/span&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;/li&gt;
&lt;li&gt;작동하는 깔끔한 코드를 작성하는 데 도움을 준다.&lt;/li&gt;
&lt;li&gt;테스트는 단순히 코드를 검증하는 것이 아니라, 책임을 수행할 객체가 기대하는 역할과 메시지를 정의하는 과정이기도 하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;05장: 책임과 메시지&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 자율적인 책임&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;lsquo;어떻게&amp;rsquo;가 아니라 &amp;lsquo;무엇&amp;rsquo;을&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자율적인 책임의 특징은 객체가 &amp;lsquo;어떻게&amp;rsquo; 해야 하는가가 아니라 &amp;lsquo;무엇&amp;rsquo;을 해야하는가를 설명한다.&lt;/li&gt;
&lt;li&gt;예를 들어, 커피 주문 시스템에서 바리스타 객체가 &quot;커피를 어떻게 만들 것인가&quot;를 직접 정의하는 것이 아니라, &quot;커피를 만든다&quot;라는 책임만을 갖는 것이 이상적이다. 이렇게 하면 바리스타 객체가 커피를 만드는 세부 과정이 변경되더라도 시스템의 다른 부분에 영향을 주지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 메시지와 메서드&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;메시지&lt;/b&gt;&lt;/span&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;/li&gt;
&lt;li&gt;메시지 - 전송 메커니즘은 객체가 다른 객체에게 접근할 수 있는 유일한 방법이다.&lt;/li&gt;
&lt;li&gt;메시지 전송은 수신자와 메시지의 조합이다. (수신자, 메시지 이름, 인자의 조합)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;다형성&lt;/span&gt;&lt;/b&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;/li&gt;
&lt;li&gt;메시지에는 처리 방법(how)과 관련된 어떤 제약도 없기 때문에, 동일한 메시지라도 서로 다른 방식의 메서드를 이용해 처리할 수 있다.&lt;/li&gt;
&lt;li&gt;따라서, 다형성을 하나의 메시지와 하나 이상의 메서드 사이의 관계로 볼 수 있다.&lt;/li&gt;
&lt;li&gt;예를 들어, &quot;음료를 제조한다&quot;라는 메시지를 전송할 때, 바리스타 객체는 커피를 만들고, 주스 제조기 객체는 오렌지 주스를 만들 수 있다. 동일한 메시지지만 각 객체는 다르게 반응한다.&lt;/li&gt;
&lt;li&gt;다형성은 객체들이 대체 가능하도록 설계를 유연하고 재사용 가능하게 만든다. 즉, 다형성은 송신자와 수신자 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮춤으로써 달성된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&amp;nbsp;메시지를 따라라&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;객체지향의 핵심, 메시지&lt;/span&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;/li&gt;
&lt;li&gt;훌륭한 객체지향 설계는 &quot;어떤 객체가 어떤 메시지를 전송할 수 있는가&quot;와 &quot;어떤 객체가 어떤 메시지를 이해할 수 있는가&quot;를 중심으로 객체 사이의 협력 관계를 구성하는 것이다.&lt;/li&gt;
&lt;li&gt;예를 들어, &quot;결제하기&quot; 메시지를 고객 객체가 전송하면, 결제 객체는 카드 결제, 현금 결제 등 다양한 방식으로 반응할 수 있도록 설계할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;What / Who 사이클&lt;/span&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;/li&gt;
&lt;li&gt;즉, &quot;무엇(What)&quot;을 먼저 정의한 후 &quot;누가(Who)&quot; 그 행위를 수행할 것인지 결정해야 한다.&lt;/li&gt;
&lt;li&gt;예를 들어, &quot;음료를 제공한다&quot;는 책임이 필요하다면, 이를 수행할 적절한 객체(바리스타, 자동판매기 등)를 나중에 결정하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;협력이라는 문맥 안에서 필요한 메시지를 먼저 결정한 후, 메시지를 수신하기에 적합한 객체를 선택한다. 그리고 수신된 메시지가 객체의 책임을 결정한다.&lt;/li&gt;
&lt;li&gt;요약하면, 객체가 어떤 메시지를 수신하고 처리할 수 있는지가 객체의 책임을 결정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;묻지 말고 시켜라 (= 데메테르 법칙)&lt;/span&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;/li&gt;
&lt;li&gt;메시지를 결정하기 전까지는 객체에 대해 고민하지 말아야 한다.&lt;/li&gt;
&lt;li&gt;예를 들어, 고객이 &quot;주문 상태를 확인한다&quot;라는 메시지를 전송할 때, 고객이 직접 주문 객체의 상세 데이터(예: 제조 중인지, 완료되었는지)를 확인하는 것이 아니라, 주문 객체가 자체적으로 상태를 응답하도록 설계하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;메시지를 결정하는 시점에서는 어떤 객체가 메시지를 수신할 것인지 알 수 없기 때문에, 메시지 송신자는 수신 객체의 내부 상태를 직접 볼 수 없다. 따라서 메시지 중심의 설계는 객체 간의 캡슐화를 강화한다.&lt;/li&gt;
&lt;li&gt;&amp;lsquo;데메테르 법칙&amp;rsquo;은 객체지향 애플리케이션이 자율적인 객체들의 공동체라는 사실을 강조한다. 즉, 객체는 다른 객체의 내부 결정에 간섭하지 말아야 하며, 모든 객체는 자신의 상태를 기반으로 스스로 결정을 내려야 한다.&lt;/li&gt;
&lt;li&gt;결과적으로, &amp;lsquo;데메테르 법칙&amp;rsquo;은 객체를 자율적으로 만들고 캡슐화를 보장하며, 결합도를 낮게 유지하여 설계를 유연하게 만든다.&lt;/li&gt;
&lt;li&gt;메시지가 &amp;lsquo;무엇&amp;rsquo;을 해야 하는지 요청하는 역할을 하는 것은:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스 크기를 감소시킨다.&lt;/li&gt;
&lt;li&gt;인터페이스 크기가 작아지면, 외부에서 해당 객체에게 의존해야 하는 부분이 줄어든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 객체 인터페이스&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;인터페이스란?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 객체가 외부와 소통하는 창구 역할을 하며, 내부 구조를 몰라도 객체를 사용할 수 있도록 해줍니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;인터페이스의 특징&lt;/b&gt;&lt;/span&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;내부 구조를 몰라도 사용할 수 있다.&lt;/b&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;/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;/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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체가 다른 객체와 상호작용할 수 있는 유일한 방법은 &amp;lsquo;메시지 전송&amp;rsquo;입니다. 따라서 객체의 인터페이스는 객체가 수신할 수 있는 메시지 목록으로 구성됩니다.&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;span style=&quot;color: #006dd7;&quot;&gt;책임, 메시지, 그리고 인터페이스&lt;/span&gt;&lt;/b&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;/li&gt;
&lt;li&gt;자율적: 자신의 의지와 판단력을 기반으로 객체 스스로 책임을 수행하는 방법을 결정할 수 있다.&lt;/li&gt;
&lt;li&gt;인터페이스: 객체가 책임을 수해하기 위해 외부로부터 메시지를 받기 위한 통로&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 인터페이스 구현의 분리&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;객체 관점에서 생각하는 방법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, drawCircle() 대신 drawShape() 같은 추상적인 인터페이스를 제공하면 원뿐만 아니라 사각형, 삼각형 등 다른 도형도 쉽게 추가할 수 있습니다.&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;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;구현&lt;/span&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 내부의 데이터와 이를 조작하는 메서드(행동)&lt;/li&gt;
&lt;li&gt;객체의 상태를 저장하는 방식과 계산 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;인터페이스와 구현의 분리 원칙&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훌륭한 객체는 마치 블랙박스처럼 내부 구현을 모르더라도 인터페이스만으로 쉽게 사용할 수 있습니다. 스마트폰의 터치스크린 인터페이스처럼, 내부 회로와 코드를 알 필요 없이 화면의 아이콘만으로 조작할 수 있는 것과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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 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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 캡슐화 (=정보은닉)&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;캡슐화의 정의&lt;/span&gt;&lt;/b&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;/li&gt;
&lt;li&gt;두 가지 관점에서 활용됨:&lt;/li&gt;
&lt;/ul&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;/li&gt;
&lt;li&gt;예를 들어, 은행 계좌 객체가 있다면 balance 필드를 외부에서 직접 수정하는 것이 아니라, deposit(amount) 메서드를 통해 변경하도록 제한하는 것입니다.&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;/li&gt;
&lt;li&gt;예를 들어, 웹 브라우저에서 버튼을 클릭하면 내부적으로 복잡한 요청 처리가 이루어지지만, 사용자는 단순히 클릭하는 행위만 수행하면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&amp;nbsp;책임의 자율성이 협력의 품질을 결정한다&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 자율적인 책임은 협력을 단순하게 만든다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, 주문 시스템에서 Order 객체가 calculateTotalPrice() 책임을 가진다면, 외부에서는 세부 계산 로직을 몰라도 해당 메서드만 호출하면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 자율적인 책임은 객체 외부와 내부를 명확하게 분리한다.&lt;/span&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;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;3. 책임이 자율적일 경우 변경의 영향을 최소화할 수 있다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, PaymentProcessor 객체가 다양한 결제 수단(카드, 계좌이체, 간편결제)을 지원할 때, 내부 로직이 변경되더라도 processPayment() 인터페이스만 유지되면 외부에는 영향이 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;4. 자율적인 책임은 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.&lt;/span&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;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;/li&gt;
&lt;li&gt;예를 들어, 자동차 객체가 move() 메시지를 수신할 수 있도록 설계하면, 전기차, 가솔린 차, 하이브리드 차 등 어떤 종류의 자동차든 동일한 방식으로 동작할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;5. 객체가 수행하는 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워진다.&lt;/span&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;/li&gt;
&lt;li&gt;예를 들어, UserAuthenticator 객체가 로그인 처리만 담당하고, 사용자 정보 관리는 UserProfileManager가 담당한다면 역할이 명확해집니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/286</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4-2#entry286comment</comments>
      <pubDate>Sun, 30 Mar 2025 16:53:23 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터/IT] 객체지향의 사실과 오해</title>
      <link>https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dICHHn/btsM05tZymJ/FtKjsgvzIVRruvmRI9fPuk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dICHHn/btsM05tZymJ/FtKjsgvzIVRruvmRI9fPuk/img.jpg&quot; data-alt=&quot;표지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dICHHn/btsM05tZymJ/FtKjsgvzIVRruvmRI9fPuk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdICHHn%2FbtsM05tZymJ%2FFtKjsgvzIVRruvmRI9fPuk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;411&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;표지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&lt;a href=&quot;https://techblog.woowahan.com/2502/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://techblog.woowahan.com/2502/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1장 &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;협력하는 객체들의 공동체&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt; &lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;역할, 책임, 협력&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템은 역할과 책임을 수행하는 객체로 분할되고, 시스템의 기능은 객체 간의 연쇄적인 요청과 응답의 흐름으로 구성된 협력으로 구현됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;커피 전문점을 객체지향적으로 바라보고 설계하고 구현하자&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;커피 전문점 도메인&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #24292e; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;도메인&lt;/b&gt;이란? 사용자들이 관심을 가지고 있는 특정 분야나 주제를 말하며 소프트웨어는 도메인에 존재하는 문제를 해결하기 위해 개발된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;커피 주문&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음 예제의 목적은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;커피 전문점에서 커피를 주문하는 과정을 객체들의 협력 관계로 구현하는 것&lt;/u&gt;입니다.&lt;/p&gt;
&lt;h4 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;커피 전문점이라는 세상&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;1. 객체들로 구성된 작은 세상으로 바라보자&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;객체지향 패러다임에서 가장 중요한 것은? 당연히&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;객체&lt;/b&gt;이죠. (클래스가 아니라.. 라는 얘기를 최근에 주위 분들께 많이 들었습니다.ㅋㅋ) 그렇기 때문에 먼저, 커피 전문점을 구성하는 요소들(손님, 바리스타 등)을 객체들로 보고 커피 전문점은 그 객체들로 이루어진 작은 세상으로 생각해보겠습니다. 손님이 커피를 주문하는 이 예제를 한 줄로 요약해보면 다음과 같습니다.&lt;/p&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;rarr; 손님이 메뉴판에서 4가지 메뉴 항목들 중 하나를 선택해서 바리스타에게 선택한 메뉴(커피)를 주문하고, 바리스타는 커피를 제조해서 손님에게 건네줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 손님, 메뉴판, 메뉴 항목들(4가지), 바리스타, 커피(4가지)가 각각 하나의 객체가 될 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; 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;커피를 주문하는 과정을 객체지향 관점에서 다시 설명하면:&lt;/p&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;rarr; 손님 객체는 메뉴판 객체 안에 적힌 메뉴 항목 객체들 중에서 하나를 선택해서 바리스타 객체에게 전달(주문)하는 것입니다. 그리고 바리스타 객체는 주문을 받은 메뉴에 해당하는 커피 객체를 제조하는 것이죠.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #24292e; text-align: start;&quot; 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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1096&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmHPCL/btsMZ4hL2qb/ZvvL55rb1jOkrVtXHIDAt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmHPCL/btsMZ4hL2qb/ZvvL55rb1jOkrVtXHIDAt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmHPCL/btsMZ4hL2qb/ZvvL55rb1jOkrVtXHIDAt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmHPCL%2FbtsMZ4hL2qb%2FZvvL55rb1jOkrVtXHIDAt0%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;1280&quot; height=&quot;1096&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1096&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;■ &lt;/b&gt;객체의 역할 특징&lt;/span&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;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;/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;/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;바리스타 A는 에스프레소를 추출할 때 15초를 선호하고, 바리스타 B는 18초를 선호할 수 있습니다. 두 바리스타 모두 '커피 제조'라는 책임을 수행하지만, 구체적인 방법은 각자 다르게 선택합니다. 객체는 자신만의 방식으로 책임을 이행할 자유가 있습니다.&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;■ &lt;/b&gt;객체가 갖춰야 할 덕목&lt;/span&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;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커피 전문점에서 손님은 바리스타에게 &quot;아메리카노 만들어!&quot;라고 명령하지 않고, &quot;아메리카노 한 잔 주문할게요&quot;라고 요청합니다. 바리스타는 이 요청에 응답하여 자신의 전문성을 발휘해 커피를 제조합니다. 객체들도 마찬가지로 서로 명령이 아닌 요청과 응답을 주고받으며 협력합니다.&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; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;02장: 이상한 나라의 객체&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;■&amp;nbsp;&lt;/b&gt;객체지향이란 무엇인가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향이란 무엇일까요? 많은 사람들이 클래스나 상속 같은 구현 메커니즘에 초점을 맞추지만, 객체지향의 진정한 본질은 다른 곳에 있습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■ 객체지향의&amp;nbsp;네&amp;nbsp;가지&amp;nbsp;핵심&amp;nbsp;개념&lt;/span&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;b&gt;상호작용하는 자율적인 객체들의 공동체&lt;/b&gt;로 바라보고, 객체를 이용해 시스템을 분할하는 방법이다.&lt;/li&gt;
&lt;li&gt;자율적인 객체란 &lt;b&gt;상태(state)와 행위(behavior)를 함께 지니며, 스스로 자신을 책임지는 객체&lt;/b&gt;이다.&lt;/li&gt;
&lt;li&gt;객체는 시스템의 행위를 구현하기 위해 &lt;b&gt;다른 객체와 협력&lt;/b&gt;한다. 각 객체는 협력 내에서 &lt;b&gt;정해진 역할&lt;/b&gt;을 수행하며, 역할은 &lt;b&gt;관련된 책임의 집합&lt;/b&gt;이다.&lt;/li&gt;
&lt;li&gt;객체는 다른 객체와 협력하기 위해 &lt;b&gt;메시지를 전송&lt;/b&gt;하고, 메시지를 수신한 객체는 &lt;b&gt;적합한 메서드를 자율적으로 선택하여 메시지를 처리&lt;/b&gt;한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&amp;nbsp;객체지향의 핵심은 클래스가 아니다&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;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 data-ke-size=&quot;size18&quot;&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;li&gt;이처럼, 커피 전문점에서 중요한 것은 바리스타라는 '직위'(클래스)가 아니라, '커피를 만드는 역할'과 '주문을 받는 역할' 간의 원활한 협력입니다. 클래스는 이러한 역할을 수행할 객체를 만드는 데 필요한 구현 메커니즘일 뿐입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&amp;nbsp;앨리스 객체: 상태, 행동, 식별자&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 객체의 특성을 이해하기 위해 이상한 나라의 앨리스를 살펴봅시다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;상태와 행동의 관계&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;상태를 결정하는 것은 행동이지만, 행동의 결과를 결정하는 것은 상태입니다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앨리스가 물약을 마시는 행동을 하면(행동) 키가 작아지는 결과가 나타납니다(상태 변화). 하지만 앨리스의 현재 키(상태)에 따라 같은 행동을 해도 다른 결과가 나올 수 있습니다. 이미 너무 작아진 앨리스가 또 물약을 마신다면 결과는 달라질 테니까요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;객체의 세 가지 특성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;상태(State)&lt;/b&gt;: 앨리스의 키, 위치, 행복 정도 등&lt;/li&gt;
&lt;li&gt;&lt;b&gt;행동(Behavior)&lt;/b&gt;: 물약 마시기, 케이크 먹기, 토끼 따라가기 등&lt;/li&gt;
&lt;li&gt;&lt;b&gt;식별자(Identity)&lt;/b&gt;: 앨리스를 다른 캐릭터와 구별할 수 있게 하는 고유한 특성&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 상태(State)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태는 왜 필요할까요? &lt;b&gt;행동의 과정과 결과를 단순하게 예측하기 위해서입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앨리스의 키(상태)를 알면 문을 통과할 수 있는지(행동의 결과) 쉽게 예측할 수 있습니다. 키가 10cm라면 작은 문도 통과할 수 있겠지만, 3m라면 불가능하겠죠.&lt;/p&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;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;/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;앨리스의 속성: 키 값(150cm), 현재 감정(기쁨) 등&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 &lt;b&gt;객체는 자신의 상태를 스스로 관리한다&lt;/b&gt;는 것입니다. 앨리스가 물약을 마시면 자신의 키를 스스로 변경합니다. 다른 사람이 앨리스의 키를 마음대로 바꿀 수는 없습니다. 이것이 객체의 자율성입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 행동(Behavior)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;행동은 상태 변경을 일으킨다(부수효과)&lt;/b&gt; 앨리스가 케이크를 먹는 행동은 그녀의 키를 크게 만드는 부수효과를 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;행동은 외부에서 관찰 가능해야 한다&lt;/b&gt; 토끼가 앨리스에게 &quot;따라와!&quot;라고 말했을 때(메시지), 앨리스가 실제로 따라가는 모습(행동)은 외부에서 관찰할 수 있어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;행동은 캡슐화를 통해 자율성을 높인다&lt;/b&gt; 토끼는 앨리스에게 &quot;따라와&quot;라고 요청만 할 뿐, 앨리스가 어떻게 움직이는지(어떤 근육을 사용하는지, 어떤 경로로 가는지)는 알 필요가 없습니다. 이런 구현 세부사항은 앨리스가 캡슐화하고 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실생활에서도 마찬가지입니다. 커피숍에서 &quot;아메리카노 주세요&quot;라고 말하면 바리스타는 어떻게 만들지 스스로 결정합니다. 우리는 제조 과정의 세부사항을 알 필요가 없죠.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;3. 식별자(Identity)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식별자는 객체를 고유하게 구분할 수 있게 해주는 특성입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;객체 vs 값&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;값(Value)&lt;/b&gt;: 상태만으로 두 인스턴스를 비교(동등성)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1달러 지폐 두 장은 같은 가치를 가지므로 동등함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체(Object)&lt;/b&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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 두 개의 동일한 아메리카노 컵이 있다면 그 내용물(상태)은 같을 수 있지만, 각각은 서로 다른 음료(객체)입니다. 한 컵을 마셔도 다른 컵은 그대로 남아있죠.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;행동이 상태를 결정한다&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설계를 할 때, 초보자는 &lt;b&gt;상태를 먼저 결정하고 행동을 나중에 정의하는 실수를 저지른다.&lt;/b&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;캡슐화를 저해한다.&lt;/b&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;/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;/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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;올바른 접근법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 전문점을 설계한다고 생각해보세요:&lt;/p&gt;
&lt;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;&quot;손님이 바리스타에게 커피를 주문하는 협력&quot;&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;&quot;손님: 메뉴 선택하기, 주문하기, 지불하기&quot;&lt;/li&gt;
&lt;li&gt;&quot;바리스타: 주문 받기, 커피 제조하기, 커피 제공하기&quot;&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;&quot;손님 객체, 바리스타 객체&quot;&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;&quot;손님: 가진 돈, 선호하는 메뉴&quot;&lt;/li&gt;
&lt;li&gt;&quot;바리스타: 제조 가능한 메뉴 목록, 기술 수준&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 협력과 행동에서 출발하면 필요한 상태가 자연스럽게 도출됩니다. 결국 객체지향 설계는 객체들이 주고받는 메시지(협력)에서 시작해야 합니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;정리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향의 핵심은 자율적인 객체들이 메시지를 주고받으며 협력하는 것입니다. 객체는 상태, 행동, 식별자를 가지며, 특히 행동을 중심으로 설계해야 합니다. 클래스는 단지 이러한 객체를 만들기 위한 구현 메커니즘일 뿐, 진정한 객체지향의 핵심은 책임과 협력에 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;03장: 타입과 추상화&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;추상화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;b&gt;목적에 부합하는 것&lt;/b&gt;이어야 한다.&lt;/li&gt;
&lt;li&gt;복잡한 문제를 다루기 위해 특정 세부사항을 감추거나 생략함으로써 &lt;b&gt;이해를 돕고 복잡성을 극복하는 방법&lt;/b&gt;이다.&lt;/li&gt;
&lt;li&gt;추상화는 두 가지 차원에서 이루어진다:
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;일반화(Generalization)&lt;/b&gt;: 사물들 간의 &lt;b&gt;공통점&lt;/b&gt;을 취하고 &lt;b&gt;차이점&lt;/b&gt;을 버려 단순하게 만드는 것.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세부사항 제거&lt;/b&gt;: 중요한 부분을 강조하기 위해 &lt;b&gt;불필요한 세부사항을 제거&lt;/b&gt;하는 것.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시: 커피 전문점의 메뉴판&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 전문점에서 메뉴판을 보면 &quot;아메리카노, 카페라떼, 카푸치노&quot; 등의 항목이 있다. 하지만, 우리는 &quot;에스프레소 베이스 음료&quot;라는 개념으로 이들을 묶을 수 있다. 즉, &lt;b&gt;각각의 메뉴는 개별적인 객체지만, 공통적인 특징을 추출하여 '에스프레소 베이스 음료'라는 개념으로 일반화할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;개념(concept)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체는 &lt;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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;심볼(Symbol):&lt;/b&gt; 개념을 가리키는 이름 (예: &quot;자동차&quot;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내연(Intension):&lt;/b&gt; 개념을 객체에 적용할 수 있는지 판단하는 조건 (예: 바퀴 4개, 엔진이 있음)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;외연(Extension):&lt;/b&gt; 개념에 속하는 객체들의 집합 (예: BMW, 테슬라, 현대차)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;분류(Classification)&lt;/span&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;/li&gt;
&lt;li&gt;객체에 특정 개념을 적용하면, 그 객체는 특정 집합의 멤버로 분류된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예시: 동물 분류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;강아지&quot;와 &quot;고양이&quot;는 다르지만, 둘 다 &quot;반려동물&quot;이라는 개념으로 묶일 수 있다. 따라서, 강아지와 고양이는 &quot;반려동물&quot;이라는 &lt;b&gt;상위 개념&lt;/b&gt;의 인스턴스로 분류될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;타입(type)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입이란 &lt;b&gt;공통적인 행동을 공유하는 객체들을 분류하는 개념&lt;/b&gt;이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 행동이 우선이다.&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;객체의 타입을 결정하는 것은 객체의 행동(Behavior)이다.&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;/b&gt;&lt;/li&gt;
&lt;li&gt;이 원칙은 객체지향 패러다임을 정의하는 중요한 개념이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예시: 자동차와 자전거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동차와 자전거는 &quot;이동 수단&quot;이라는 공통점을 가진다. 하지만 내부 구조(데이터)는 다르다. 중요한 것은 &quot;이동한다&quot;는 행동이며, 이동 수단이라는 타입을 정의할 때 &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;b&gt;다형성(Polymorphism)&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;/b&gt;&lt;/li&gt;
&lt;li&gt;하지만 &lt;b&gt;행동을 처리하는 방식은 다를 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;예를 들어, 자동차는 엔진을 이용해 이동하고, 자전거는 사람이 페달을 밟아 이동한다.&lt;/li&gt;
&lt;li&gt;다형성은 &lt;b&gt;동일한 요청에 대해 객체가 서로 다른 방식으로 응답할 수 있는 능력&lt;/b&gt;이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캡슐화(Encapsulation)&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;/b&gt;해야 한다.&lt;/li&gt;
&lt;li&gt;예를 들어, 자동차 객체의 내부 연료 상태를 외부에서 직접 변경할 수 없도록 하고, &quot;주유하기&quot;라는 행동을 통해서만 상태를 변경할 수 있도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 일반화 / 특수화 관계&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;일반화(Generalization):&lt;/b&gt; 여러 개체의 공통점을 모아 상위 개념을 만드는 과정.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특수화(Specialization):&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;/b&gt;할 수 있지만, &lt;b&gt;행동의 수는 적다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;특수화된 개념은 &lt;b&gt;더 적은 객체를 포함&lt;/b&gt;하지만, &lt;b&gt;행동의 수는 더 많다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&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;동물&quot;은 일반화된 개념이다.&lt;/li&gt;
&lt;li&gt;&quot;포유류&quot;는 동물보다 특수화된 개념이며, &quot;젖을 먹인다&quot;라는 추가적인 행동을 가진다.&lt;/li&gt;
&lt;li&gt;따라서, &quot;포유류&quot;는 &quot;동물&quot;보다 더 좁은 집합이지만, 더 많은 행동을 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 슈퍼타입 / 서브타입&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;슈퍼타입(Supertype):&lt;/b&gt; 일반화된 타입.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서브타입(Subtype):&lt;/b&gt; 특수화된 타입.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서브타입은 슈퍼타입의 행동을 그대로 수행할 수 있어야 한다. &amp;rarr; &lt;b&gt;행위적 호환성(Behavioral Compatibility)을 만족해야 한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&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;직원(Employee)&quot;은 슈퍼타입이고, &quot;매니저(Manager)&quot;는 서브타입이다.&lt;/li&gt;
&lt;li&gt;매니저는 직원이 수행하는 모든 행동을 할 수 있지만, 추가적으로 &quot;팀 관리&quot;라는 행동을 가질 수 있다.&lt;/li&gt;
&lt;li&gt;따라서, &quot;매니저&quot;는 &quot;직원&quot;을 대체할 수 있어야 한다. (Liskov Substitution Principle, LSP)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 타입의 목적: 객체 상태의 정적 표현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입은 &lt;b&gt;동적으로 변하는 객체의 상태를 정적인 관점에서 표현&lt;/b&gt;할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피를 예로 들면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동적 상태: 온도가 낮아지고, 양이 줄어들고, 맛이 변하는 등&lt;/li&gt;
&lt;li&gt;정적 표현: '아메리카노'라는 타입으로 추상화&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 타입은 변화하는 현실 세계를 프로그램 안에서 안정적으로 다룰 수 있게 해주는 추상화 장치입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #24292e; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;■&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;정리&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체를 분류하는 기준은 타입이며, 타입을 나누는 기준은 객체가 수행하는 행동이다.&lt;/li&gt;
&lt;li&gt;객체를 분류하기 위해 타입을 결정한 후 프로그래밍 언어를 이용해 타입을 구현할 수 있는 한가지 방법이 클래스이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/285</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%BB%B4%ED%93%A8%ED%84%B0IT-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4#entry285comment</comments>
      <pubDate>Sun, 30 Mar 2025 14:13:19 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 클로저, 렉시컬 환경, 실행 컨텍스트</title>
      <link>https://steady-record.tistory.com/entry/JavaScript-%ED%81%B4%EB%A1%9C%EC%A0%80-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BD-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;클로저&lt;/h2&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;b&gt;렉시컬 환경&lt;/b&gt;(Lexical Environment)을 기억하여 외부 함수가 종료된 후에도 내부 함수가 외부 변수에 접근할 수 있도록 하는 기능이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;여기서 렉시컬 환경은 또 무엇일까?&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;렉시컬 환경&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;렉시컬 환경은 &quot;자바스크립트 엔진이 변수와 함수 선언을 관리하기 위해 사용하는 구체적인 공간&quot;을 말한다.&lt;/li&gt;
&lt;li&gt;렉시컬 스코프는 &quot;함수의 정의 위치를 기준으로 스코프가 결정되는 규칙&quot;을 의미하는 것으로 렉시컬 환경과는 다른 의미를 가진다.&lt;/li&gt;
&lt;li&gt;예시:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736077666072&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function makeAdder(x) {
	return function(y) {
		return x + y;
	}
}

const add3 = makeAdder(3);
console.log(add3(2));		// 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;makeAdder(3)이 호출되면, 반환된 내부 함수는 x의 값 3을 렉시컬 스코프를 통해 기억한다.&lt;/li&gt;
&lt;li&gt;add3 변수는 makeAdder(3) 호출의 반환 값인 함수(내부 함수)를 참조한다.&lt;/li&gt;
&lt;li&gt;최종적으로 add3(2)를 호출하면 내부 함수가 실행되면 y는 2로 전달된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736077962962&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function makeAdder(x) {
	return function(y) {
		return x + y;
	}
}

const add3 = function(y) {
                return 3 + y;
            }
            
console.log(function(2) {
                return 3 + 2;
            });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 코드를 렉시컬 환경으로 나타내면 아래와 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byAaGW/btsLDXQVBXQ/FOa53m01hqOnKmE3TklZ4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byAaGW/btsLDXQVBXQ/FOa53m01hqOnKmE3TklZ4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byAaGW/btsLDXQVBXQ/FOa53m01hqOnKmE3TklZ4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyAaGW%2FbtsLDXQVBXQ%2FFOa53m01hqOnKmE3TklZ4K%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;700&quot; height=&quot;342&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;다시 돌아와, 클로저의 예시를 살펴보자:&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736076024522&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function outer() {
  const x = 'outer scope';

  function inner() {
    return x; // inner는 x를 기억한다.
  }

  return inner;
}

const myInner = outer();
console.log(myInner()); // &quot;outer scope&quot;&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;위 코드에서 outer 함수가 종료된 후에도, inner 함수는 x를 참조할 수 있다.&lt;/li&gt;
&lt;li&gt;이는 inner 함수가 렉시컬 스코프를 기반으로 작성되었기 때문에, outer 함수의 스코프 체인을 기억하기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;클로저를 통해 은닉화도 가능하다.&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736077550365&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function makeCounter() {
	let num = 0;	//은닉화
	return function() {
		return num++;
	};
}

let counter = makeCounter();
console.log(counter());
console.log(counter());
console.log(counter());&lt;/code&gt;&lt;/pre&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;makeCounter 호출&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;makeCounter가 실행되며, num에 0이 저장된다.&lt;/li&gt;
&lt;li&gt;반환된 내부 함수는 num을 포함한 클로저를 형성한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;counter 함수 호출&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부 함수가 실행되며, 클로저를 통해 num에 접근한다.&lt;/li&gt;
&lt;li&gt;num 값이 반환된 후 증가한다.&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;num은 외부에서 직접 접근할 수 없고, 오직 counter 함수 호출을 통해서만 접근할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 컨텍스트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 컨텍스트는 현재 실행중인&amp;nbsp;코드에 대한 세부 정보(제어 흐름의 위치, 선언된 변수와 함수, this, arguments 등) 를 담고있는 데이터 구조이다.&lt;/li&gt;
&lt;li&gt;실행 컨택스트의 종류는 아래와 같이 두 가지가 있다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;1. Global Execution Context&amp;nbsp;&amp;nbsp;-&amp;nbsp; 스크립트가 처음 실행될때 생성된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;2. Function Execution Context&amp;nbsp; -&amp;nbsp; 함수가 호출될때 생성된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 생성된 Global Execution Context 와 Function Execution Context는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;실행 컨택스트 스택 이라는 자료구조에&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저장 되고 관리된다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 스택은 &lt;b&gt;호출스택(call stack)&lt;/b&gt; 이라고도 부르고, '스택' 이므로 후입선출 방식으로 컨택스트를 push / pop 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;동작방식&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;Global Execution Context&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스크립트 실행 시 가장 처음 생성되며, 항상 스택의 가장 아래에 위치한다.&lt;/li&gt;
&lt;li&gt;이후 함수가 호출되면 해당 함수의 실행 컨텍스트가 만들어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Function Execution Context&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;push&lt;/b&gt;된다.&lt;/li&gt;
&lt;li&gt;함수 실행이 종료되면 스택에서 &lt;b&gt;pop&lt;/b&gt;되어 제거된다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736078547617&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
    // 스크립트 실행 -&amp;gt; Global Execution Context 가 생성되고 스택에 push된다.
    
    function A(){
    	B(); // 함수B 의 실행 컨택스트가 생성되고 스택에 push.
    }
    
    function B(){
    	console.log('done!'); 
    }   
    
    A(); // 함수A 의 실행 컨택스트가 생성되고 스택에 push.
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;755&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tM14I/btsLDHU3vhe/MN2vK49Vmr1kvsMrnMZmk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tM14I/btsLDHU3vhe/MN2vK49Vmr1kvsMrnMZmk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tM14I/btsLDHU3vhe/MN2vK49Vmr1kvsMrnMZmk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtM14I%2FbtsLDHU3vhe%2FMN2vK49Vmr1kvsMrnMZmk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;755&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;755&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;그래서 실행 컨텍스트와 렉시컬 환경의 관계는 어떻게 될까?&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qtCft/btsLDIfsvOX/hgYYs64Puv9BKogtLad0Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qtCft/btsLDIfsvOX/hgYYs64Puv9BKogtLad0Ik/img.png&quot; data-alt=&quot;실행 컨텍스트 내부 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qtCft/btsLDIfsvOX/hgYYs64Puv9BKogtLad0Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqtCft%2FbtsLDIfsvOX%2FhgYYs64Puv9BKogtLad0Ik%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;507&quot; height=&quot;178&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 컨텍스트 내부 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실행 컨텍스트는 렉시컬 환경을 포함하며, 실행 중인 코드의 실행 정보를 관리한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; 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;는 자바스크립트 코드 실행의 핵심 도구이며, 실제로 실행 흐름을 제어하는 &quot;실행 도구&quot;로 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렉시컬 환경에 저장된 변수/함수, this, 제어 흐름 위치를 포함해 코드 실행에 필요한 모든 정보를 담고 있고 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;스택 자료구조(Call Stack)를 기반으로 컨텍스트를 생성, 실행, 제거하며, 코드 실행 순서를 제어한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 실행 컨텍스트는 &lt;b&gt;렉시컬 환경을 활용하여 변수와 스코프를 관리&lt;/b&gt;하고, &lt;b&gt;스택 자료구조를 통해 실행 흐름을 제어&lt;/b&gt;하는 도구로 이해할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://kwangsunny.tistory.com/37&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kwangsunny.tistory.com/37&lt;/a&gt;&lt;/p&gt;</description>
      <category>WEB/JavaScript</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/284</guid>
      <comments>https://steady-record.tistory.com/entry/JavaScript-%ED%81%B4%EB%A1%9C%EC%A0%80-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BD-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8#entry284comment</comments>
      <pubDate>Sun, 5 Jan 2025 21:19:09 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 호이스팅, 스코프</title>
      <link>https://steady-record.tistory.com/entry/JavaScript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EC%8A%A4%EC%BD%94%ED%94%84</link>
      <description>&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;자바스크립트 호이스팅과 스코프&lt;/span&gt;&lt;/h2&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;또한 변수나 함수가 어떤 범위(scope)에서 유효한지에 따라 여러 가지 특징적인 동작을 보인다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;호이스팅&lt;/b&gt;&lt;/h2&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;예시:&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736071428275&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(score); // undefined
var score;
score = 100;
console.log(score); // 100&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 &quot;아직 선언되지 않은 변수를 console.log로 출력하면 에러가 발생해야 하는 것 아닌가?&quot;라고 생각할 수도 있지만, 자바스크립트에서는 위 예시처럼 `undefined`가 출력된다.&lt;/li&gt;
&lt;li&gt;이는 `var score;` 선언이 런타임 이전에 미리 처리되었기 때문이다. 이처럼 선언이 코드의 최상단으로 끌어올려진 것처럼 동작하는 것을 호이스팅이라고 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변수 호이스팅&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 예시에서 `var` 키워드를 사용한 변수는 선언과 동시에 초기화가 되므로 `undefined`가 출력되었다.&lt;/li&gt;
&lt;li&gt;`let`, `const`로 선언한 경우에는 어떤 결과가 될까?&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736072163784&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;console.log(age); // ReferenceError
let age = 30;&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;이&amp;nbsp;경우,&amp;nbsp;age&amp;nbsp;변수가&amp;nbsp;호이스팅되었더라도,&amp;nbsp;초기화는&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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 호이스팅&lt;/h3&gt;
&lt;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;b&gt;변수 호이스팅&lt;/b&gt;과는 &lt;b&gt;미묘한 차이&lt;/b&gt;가 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736072274490&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 함수 참조
console.dir(add); // f add(x, y)
console.dir(sub); // undefined

// 함수 호출
console.log(add(2, 5)); // 7
console.log(sub(2, 5)); // TypeError: sub is not a function

// 함수 선언문
function add(x, y) {
  return x + y;
}

// 함수 표현식
var sub = function (x, y) {
  return x - y;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;함수 선언문&lt;/b&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;함수 표현식&lt;/b&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;따라서 초기화 이전에 함수를 호출하면 에러(TypeError)가 발생하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;스코프(Scope)&lt;/h2&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;&quot;코드 어디에서 해당 변수/함수에 접근할 수 있는가?&quot;를 정하는 영역&lt;/li&gt;
&lt;li&gt;스코프는 크게 &lt;b&gt;전역 스코프&lt;/b&gt;와 &lt;b&gt;지역 스코프&lt;/b&gt;로 구분된다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스코프 체인(Scope Chain)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 현재 스코프에서 시작하여 상위(외부) 스코프 방향으로 이동하며 변수를 검색한다.&lt;/li&gt;
&lt;li&gt;예시:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736072671178&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const x = &quot;global x&quot;;
const y = &quot;global y&quot;;

function outer() {
  const y = &quot;outer's local y&quot;;

  function inner() {
    const z = &quot;inner's local z&quot;;
    console.log(x); // &quot;global x&quot;
    console.log(y); // &quot;outer's local y&quot;
    console.log(z); // &quot;inner's local z&quot;
  }
  
  inner();
  // console.log(z); // ReferenceError: z is not defined
}

outer();&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;inner 함수 내부에서는 outer 함수에 정의된 y에 접근이 가능하지만, outer 함수 내부에서는 inner 함수의 z에 접근할 수 없다. 이것이 스코프 체인과 렉시컬 스코프(정적 스코프)의 특징이다. &lt;/li&gt;
&lt;li&gt;해당 코드에 대한 스코프 체인은 아래 그림과 같이 구성되어 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3aTQ7/btsLEfRj9fo/3jsolbIbjMvzxUpqBugzlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3aTQ7/btsLEfRj9fo/3jsolbIbjMvzxUpqBugzlk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3aTQ7/btsLEfRj9fo/3jsolbIbjMvzxUpqBugzlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3aTQ7%2FbtsLEfRj9fo%2F3jsolbIbjMvzxUpqBugzlk%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;300&quot; height=&quot;592&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;var 키워드로 선언된 변수나, &lt;b&gt;함수 선언문&lt;/b&gt;으로 만들어진 함수는 &lt;b&gt;함수 레벨 스코프&lt;/b&gt;를 갖는다고 볼 수 있다.&lt;/li&gt;
&lt;li&gt;이는 &quot;함수 내부 전체에서만 유효&quot;하다는 의미이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1736073800453&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function foo() {
  if (true) {
    var color = 'blue';
  }
  console.log(color); // blue
}
foo();&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;2. 블록 레벨 스코프&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;`let`이나 `const`로 선언한 변수는 블록 레벨 스코프를 따르므로, 해당 블록(`{ ... }`) 내부에서만 유효하며 블록을 벗어나면 참조할 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736073906357&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function foo() {
  if (true) {
    let color = 'blue';
    console.log(color); // blue
  }
  console.log(color); // ReferenceError
}
foo();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UUGvL/btsLEL3x4w3/dY9qrTkPYEIsVxCr21JH61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UUGvL/btsLEL3x4w3/dY9qrTkPYEIsVxCr21JH61/img.png&quot; data-alt=&quot;함수 레벨 스코프와 블록 레벨 스코프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UUGvL/btsLEL3x4w3/dY9qrTkPYEIsVxCr21JH61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUUGvL%2FbtsLEL3x4w3%2FdY9qrTkPYEIsVxCr21JH61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;281&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;함수 레벨 스코프와 블록 레벨 스코프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 렉시컬 스코프&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;ldquo;함수의&lt;b&gt; 선언&lt;/b&gt; 위치에 의해 상위 스코프가 정해진다&amp;rdquo;는 언어적 특성 또는 개념이다.&lt;/li&gt;
&lt;li&gt;정적 스코프(Static Scope) 라고도 불린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렉시컬 스코프의 동작&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수가 선언될 당시의 &lt;b&gt;스코프 체인&lt;/b&gt;이 함수의 상위 스코프로 결정된다.&lt;/li&gt;
&lt;li&gt;함수가 &lt;b&gt;호출&lt;/b&gt;된 위치는 스코프 결정에 영향을 미치지 않는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;예시:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736075685585&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var a = 10;

function first() {
  var a = 20;
  second();
}

function second() {
  console.log(a);
}

first(); // ?
second(); // ?&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;실행 결과로는 10, 10이 출력된다. second함수가 first함수 안에서 호출되었다고 하더라도 second함수가 선언된 위치는 전역 스코프이므로 전역 변수인 a를 참조하여 10이 출력되는 것이다.&lt;/li&gt;
&lt;li&gt;이러한 개념은&amp;nbsp;&lt;b&gt;클로저&lt;/b&gt;와 매우 밀접하게 연관되어 있다. 클로저는 다음 게시물에서 확인해본다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&lt;a href=&quot;https://velog.io/@ahhpc2012/javascript-scope&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@ahhpc2012/javascript-scope&lt;/a&gt;&lt;/p&gt;</description>
      <category>WEB/JavaScript</category>
      <category>변수 호이스팅</category>
      <category>함수 호이스팅</category>
      <category>호이스팅</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/283</guid>
      <comments>https://steady-record.tistory.com/entry/JavaScript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EC%8A%A4%EC%BD%94%ED%94%84#entry283comment</comments>
      <pubDate>Sun, 5 Jan 2025 20:18:24 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 변수 선언, 함수 정의 및 형태</title>
      <link>https://steady-record.tistory.com/entry/JavaScript-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98-%EB%B0%8F-%ED%98%95%ED%83%9C</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;변수&lt;/b&gt;&lt;/h2&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; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터를 저장하기 위해 이름을 부여한 메모리 공간을 의미한다. 프로그램을 작성할 때 필요한 값을 저장하고 꺼내 쓰는 역할을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변수 선언&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수를 사용하기 위해 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것이다.&lt;/li&gt;
&lt;li&gt;선언 키워드 : var, let, const&lt;/li&gt;
&lt;li&gt;ES6버전에서 var의 단점을 보완한 let, const 가 도입되면서 var는 잘 사용하지 않는다.&lt;/li&gt;
&lt;li&gt;선언 후 초기화를 해주지 않으면 변수의 값에는 쓰레기 값이 들어간다. var로 선언을 하면 자동으로 &lt;code&gt;undefined&lt;/code&gt;로 초기화가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;변수의 생성과정&lt;/b&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;/li&gt;
&lt;li&gt;초기화 (undefined를 할당주는 단계)&lt;/li&gt;
&lt;li&gt;할당&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;var와 let의 차이점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;var는 선언과 초기화가 동시에 된다. 그래서 할당 전에 호출하면 'undefined'가 나온다.&lt;/li&gt;
&lt;li&gt;let은 선언단계와 초기화 단계가 분리되어서 진행된다. 호이스팅되면서 선언단계가 이루어지지만 초기화는 코드가 실행됐을 때 수행되기 때문에 에러가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;var name;
console.log(name);    // undefined


let name;
console.log(name);    //ReferenceError&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&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;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;함수&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 정의&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수정의란 함수를 호출하기 이전에 인수를 전달받을 매개변수와 실행할 문들, 그리고 반환할 값을 지정하는 것을 말한다.&lt;/li&gt;
&lt;li&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;Function 생성자 함수&lt;/li&gt;
&lt;li&gt;화살표 함수&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 함수 선언문&lt;/h4&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;javascript&quot;&gt;&lt;code&gt;function add(x, y) {
    return x + y;

// 함수 참조
// console.dir은 console.log와는 달리 함수 객체의 프로퍼티까지 출력한다.
console.dir(add);     // f add(x, y)

// 함수 호출
console.log(add(2, 5))  // 7&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 함수 표현식&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 리터럴로 생성한 함수 객체를 변수에 할당하는 방식&lt;/li&gt;
&lt;li&gt;함수 리터럴의 함수 이름은 생략할 수 있다. 이러한 함수를 익명 함수라 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;var add = function(x, y) {
    return x + y;
};

// 함수 객체를 가리키는 식별자로 호출
console.log(add(2, 5));   // 7&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. Function 생성자 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JS가 기본 제공하는 빌트인 함수인 Function 생성자 함수에 매개변수 목록과 함수 몸체를 문자열로 전달하면서 &lt;code&gt;new&lt;/code&gt;연산자와 함께 호출하면 함수 객체를 생성해서 반환하다.&lt;/li&gt;
&lt;li&gt;Function 생성자 함수로 함수를 생성하는 방식은 일반적이지 않으며 바람직하지도 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 함수(constructor function)&lt;br /&gt;객체를 생성하는 함수를 말한다. 객체를 생성하는 방식은 객체 리터럴 이외에 다양한 방법이 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;var add = new Function('x', 'y', 'return x + y');
console.log(add(2, 5));        // 7&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 화살표 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ES6에서 도입된 화살표 함수는 항상 익명함수로 정의한다.&lt;/li&gt;
&lt;li&gt;생성자 함수로 사용할 수 없으며, 기존 함수와 &lt;code&gt;this&lt;/code&gt; 바인딩 방식이 다르고, &lt;code&gt;prototype&lt;/code&gt; 프로퍼티가 없으며 &lt;code&gt;arguments&lt;/code&gt; 객체를 생성하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 화살표 함수
const add = (x, y) =&amp;gt; x + y;
console.log(add(2, 5));        // 7&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수의 형태&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 즉시 실행 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 정의와 동시에 즉시 호출되는 함수&lt;/li&gt;
&lt;li&gt;단 한 번만 호출되며 다시 호출할 수 없다.&lt;/li&gt;
&lt;li&gt;익명 함수를 사용하는 것이 일반적이나 함수 이름이 있는 기명 즉시 실행 함수도 사용할 수 있다. 하지만 함수 선언문이 아니라 함수 리터럴로 평가되며 함수 이름은 함수 몸체에서만 참조할 수 있는 식별자이므로 다시 호출할 수는 없다.&lt;/li&gt;
&lt;li&gt;즉시 실행 함수는 반드시 그룹 연산자 &lt;code&gt;(...)&lt;/code&gt;로 감싸야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// 기명 즉시 실행 함수
(function foo() {
    var a = 3;
    var b = 5;
    return a * b;
}());

foo();        // ReferenceError: foo is not defined

// 즉시 실행 함수도 일반 함수처럼 값을 반환할 수 있다.
var res = (function() {
    var a = 3;
    var b = 5;
    return a * b;
}());

console.log(res);    // 15&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 재귀 함수&lt;/h4&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;actionscript&quot;&gt;&lt;code&gt;// 팩토리얼은 1부터 자신까지의 모든 양의 정수의 곱이다.
// n! = 1 * 2 * ... * (n - 1) * n
function factorial(n) {
    // 탈출 조건: n이 1 이하일 때 재귀 호출을 멈춘다.
    if (n &amp;lt;= 1) return 1;
    // 재귀호출
    return n * factorial(n - 1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 중첩 함수&lt;/h4&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;javascript&quot;&gt;&lt;code&gt;function outer() {
    var x = 1;

    // 중첩 함수
    function inner() {
        var y = 2;
        // 외부 함수의 변수를 참조할 수 있다.
        console.log(x + y);        // 3
    }
    inner();
}

outer();&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 콜백 함수&lt;/h4&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;b&gt;콜백 함수&lt;/b&gt; : 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수&lt;/li&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 고차 함수
// 외부에서 전달받은 f를 n번 반복 호출
function repeat(n, f) {
  for (var i = 0; i &amp;lt; n; i++) {
    f(i); // i를 전달하며 f 호출
  }
}

// 콜백 함수1
var logAll = function(i) {
  console.log(i);
};

// 고차 함수에 콜백 전달
repeat(5, logAll); // 0 1 2 3 4

// 콜백 함수2
var logOdds = function(i) {
  if (i % 2) console.log(i);
};

repeat(5, logOdds); // 1 3&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;콜백 함수는 비동기 처리(이벤트 처리, Ajax 통신, 타이머 함수 등)에 활용되는 중요한 패턴이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 콜백 함수를 사용한 이벤트 처리
document.getElementById('myButton').addEventListener('click', function() {
  console.log('button clicked');
});

// 콜백 함수를 사용한 비동기 처리
setTimeout(function() {
  console.log('1초 경과');
}, 1000);&lt;/code&gt;&lt;/pre&gt;</description>
      <category>WEB/JavaScript</category>
      <category>자바스크립트 변수선언</category>
      <category>자바스크립트 함수정의</category>
      <category>콜백함수</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/282</guid>
      <comments>https://steady-record.tistory.com/entry/JavaScript-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98-%EB%B0%8F-%ED%98%95%ED%83%9C#entry282comment</comments>
      <pubDate>Sun, 5 Jan 2025 18:44:43 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 백준 1427번 : 소트인사이드 (java) + 선택 정렬 알고리즘</title>
      <link>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-1427%EB%B2%88-%EC%86%8C%ED%8A%B8%EC%9D%B8%EC%82%AC%EC%9D%B4%EB%93%9C-java-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1427&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1427&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❓문제&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1169&quot; data-origin-height=&quot;723&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WyMAD/btsKtNCbMpg/T3vvjAEjvDegDiWUaSiIpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WyMAD/btsKtNCbMpg/T3vvjAEjvDegDiWUaSiIpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WyMAD/btsKtNCbMpg/T3vvjAEjvDegDiWUaSiIpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWyMAD%2FbtsKtNCbMpg%2FT3vvjAEjvDegDiWUaSiIpK%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;1169&quot; height=&quot;723&quot; data-origin-width=&quot;1169&quot; data-origin-height=&quot;723&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; 해석&lt;/b&gt;&lt;/h2&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;1.&amp;nbsp;남은&amp;nbsp;정렬&amp;nbsp;부분에서&amp;nbsp;최솟값&amp;nbsp;또는&amp;nbsp;최댓값을&amp;nbsp;찾는다. &lt;br /&gt;2.&amp;nbsp;남은&amp;nbsp;정렬&amp;nbsp;부분에서&amp;nbsp;가장&amp;nbsp;앞에&amp;nbsp;있는&amp;nbsp;데이터와&amp;nbsp;선택된&amp;nbsp;데이터를&amp;nbsp;swap&amp;nbsp;한다. &lt;br /&gt;3.&amp;nbsp;가장&amp;nbsp;앞에&amp;nbsp;있는&amp;nbsp;데이터의&amp;nbsp;위치를&amp;nbsp;변경해&amp;nbsp;남은&amp;nbsp;정렬&amp;nbsp;부분의&amp;nbsp;범위를&amp;nbsp;축소한다. &lt;br /&gt;4.&amp;nbsp;전체&amp;nbsp;데이터&amp;nbsp;크기만큼&amp;nbsp;index가&amp;nbsp;커질&amp;nbsp;때까지,&amp;nbsp;즉&amp;nbsp;남은&amp;nbsp;정렬&amp;nbsp;부분이&amp;nbsp;없을&amp;nbsp;때까지&amp;nbsp;반복한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;⭕정답 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1695559028389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		String input = br.readLine();
		
		int[] inputs = new int[input.length()];
		for (int i = 0; i &amp;lt; input.length(); i++) {
			inputs[i] = input.charAt(i) - '0';
		}
		
		selectionSort(inputs);
		String result = inputsToStr(inputs);
		
		System.out.println(result);
	}

	private static void selectionSort(int[] inputs) {
		int len = inputs.length;
		int idx = 0;
		
		// 선택정렬 과정
		while (idx &amp;lt; len) {		// 4. 전체 데이터 크기만큼 index가 커질 때까지, 즉 남은 정렬 부분이 없을 때까지 반복한다.
			int maxIdx = idx;
			for (int i = idx; i &amp;lt; len ; i++) {
				// 1. 남은 정렬 부분에서 최솟값 또는 최댓값을 찾는다.
				if (inputs[maxIdx] &amp;lt; inputs[i]) {
					maxIdx = i;
				}
			}
			// 2. 남은 정렬 부분에서 가장 앞에 있는 데이터와 선택된 데이터를 swap 한다.
			swap(inputs, idx, maxIdx);
			// 3. 가장 앞에 있는 데이터의 위치를 변경해 남은 정렬 부분의 범위를 축소한다.
			idx++;
		}
	}

	private static String inputsToStr(int[] inputs) {
		StringBuilder sb = new StringBuilder();
		
		for (int val : inputs) {
			sb.append(val);
		}
		return sb.toString();
	}

	private static void swap(int[] inputs, int idx, int maxIdx) {
		int temp = inputs[idx];
		inputs[idx] = inputs[maxIdx];
		inputs[maxIdx] = temp;
	}
}&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;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❗결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/74ADH/btsKuuu31EV/saHO770Nm1QndU5KJr00ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/74ADH/btsKuuu31EV/saHO770Nm1QndU5KJr00ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/74ADH/btsKuuu31EV/saHO770Nm1QndU5KJr00ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F74ADH%2FbtsKuuu31EV%2FsaHO770Nm1QndU5KJr00ck%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;1157&quot; height=&quot;91&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;91&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩테스트/백준</category>
      <category>문자열</category>
      <category>선택 정렬</category>
      <category>정렬</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/281</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-1427%EB%B2%88-%EC%86%8C%ED%8A%B8%EC%9D%B8%EC%82%AC%EC%9D%B4%EB%93%9C-java-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98#entry281comment</comments>
      <pubDate>Fri, 1 Nov 2024 23:06:03 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 백준 23968번 : 알고리즘 수업 - 버블 정렬 1 (java)</title>
      <link>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-23968%EB%B2%88-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%88%98%EC%97%85-%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-1-java</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/23968&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/23968&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;알고리즘 분류 : 구현,&amp;nbsp;정렬,&amp;nbsp;시뮬레이션&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❓문제&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baOMav/btsKtlZOq69/BsCfC5lthkd9t3XsPj96XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baOMav/btsKtlZOq69/BsCfC5lthkd9t3XsPj96XK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baOMav/btsKtlZOq69/BsCfC5lthkd9t3XsPj96XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaOMav%2FbtsKtlZOq69%2FBsCfC5lthkd9t3XsPj96XK%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;1166&quot; height=&quot;631&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRBbKK/btsKudzE4iU/6KSJ0o9l9kxkv5kuCz9xlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRBbKK/btsKudzE4iU/6KSJ0o9l9kxkv5kuCz9xlk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRBbKK/btsKudzE4iU/6KSJ0o9l9kxkv5kuCz9xlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRBbKK%2FbtsKudzE4iU%2F6KSJ0o9l9kxkv5kuCz9xlk%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;1157&quot; height=&quot;700&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; 해석&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교 기반 정렬 알고리즘인 버블 정렬을 활용하는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 양옆에 위치한 두 값을 비교하면서 크기 순으로 정렬한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 동안은 전역변수, 지역변수 신경 쓰지않고 작성했지만 이제부터 ChatGPT-4o에게 코드리뷰를 받고 코딩 습관을 고치려고 한다.&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;pre id=&quot;code_1730446017852&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

//백준 23968번
public class Main {

	static int N, K;
	static int[] inputs;
	
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		
		inputs = new int[N];
		
		// 배열 입력받기
		st = new StringTokenizer(br.readLine());
		for (int i = 0; i &amp;lt; N; i++) {
			inputs[i] = Integer.parseInt(st.nextToken());
		}
		
		int cnt = 0;	//정렬 횟수
		int temp = 0;
		boolean isEnd = false;
		for (int i = 0; i &amp;lt; N - 1; i++) {
			for (int j = 0; j &amp;lt; N - 1; j++) {
				if (inputs[j] &amp;gt; inputs[j + 1]) {
					temp = inputs[j];
					inputs[j] = inputs[j + 1];
					inputs[j + 1] = temp;
					cnt++;
				}
				
				if (cnt &amp;gt;= K) {
					System.out.printf(&quot;%d %d&quot;, inputs[j], inputs[j + 1]);
					isEnd = true;
					return;
				}
			}
			
		}
		
		if (!isEnd) System.out.println(-1);
		br.close();
	}
}&lt;/code&gt;&lt;/pre&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;p data-ke-size=&quot;size16&quot;&gt;1&amp;nbsp;전역 변수를 최소화 &lt;br /&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;좋습니다. &lt;br /&gt;&lt;br /&gt;2.&amp;nbsp;메서드&amp;nbsp;분리 &lt;br /&gt;-&amp;nbsp;main&amp;nbsp;메서드를&amp;nbsp;간결하게&amp;nbsp;유지하고&amp;nbsp;코드&amp;nbsp;가독성과&amp;nbsp;재사용성을&amp;nbsp;높입니다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;⭕정답 코드(코드리뷰 후)&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1695559028389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

//백준 23968번
public class Main {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int N = Integer.parseInt(st.nextToken());
		int K = Integer.parseInt(st.nextToken());
		
		int[] inputs = new int[N];
		
		// 배열 입력받기
		st = new StringTokenizer(br.readLine());
		for (int i = 0; i &amp;lt; N; i++) {
			inputs[i] = Integer.parseInt(st.nextToken());
		}
		
		bubbleSort(N, K, inputs);
	}

	private static void bubbleSort(int N, int K, int[] inputs) {
		int cnt = 0;
		
		for (int i = 0; i &amp;lt; N - 1; i++) {
			for (int j = 0; j &amp;lt; N - 1; j++) {
				if (inputs[j] &amp;gt; inputs[j + 1]) {
					swap(inputs, j, j + 1);
					cnt++;
				}
				
				if (cnt &amp;gt;= K) {
					System.out.printf(&quot;%d %d&quot;, inputs[j], inputs[j + 1]);
					return;
				}
			}
			
		}
		
		System.out.println(-1);
	}

	private static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
	}
}&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;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❗결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4xaEU/btsKtU1w7OM/8Kv7u1hHA5fKmOz90QAdkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4xaEU/btsKtU1w7OM/8Kv7u1hHA5fKmOz90QAdkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4xaEU/btsKtU1w7OM/8Kv7u1hHA5fKmOz90QAdkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4xaEU%2FbtsKtU1w7OM%2F8Kv7u1hHA5fKmOz90QAdkk%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;700&quot; height=&quot;74&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;74&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;</description>
      <category>코딩테스트/백준</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/280</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-23968%EB%B2%88-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%88%98%EC%97%85-%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-1-java#entry280comment</comments>
      <pubDate>Fri, 1 Nov 2024 17:06:43 +0900</pubDate>
    </item>
    <item>
      <title>[삼성SDS] 24년 하반기 대학생 알고리즘 특강(Day9) : 최단거리 알고리즘(다익스트라, 벨만-포드, 플로이드-워셜)</title>
      <link>https://steady-record.tistory.com/entry/%EC%82%BC%EC%84%B1SDS-24%EB%85%84-%ED%95%98%EB%B0%98%EA%B8%B0-%EB%8C%80%ED%95%99%EC%83%9D-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%8A%B9%EA%B0%95Day9-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%8B%A4%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%9D%BC-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%ED%94%8C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9B%8C%EC%85%9C</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다익스트라 알고리즘 (Dijkstra's Algorithm)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;li&gt;시작점이&amp;nbsp;있고,&amp;nbsp;모든&amp;nbsp;노드로&amp;nbsp;최단&amp;nbsp;거리를&amp;nbsp;구할&amp;nbsp;때&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;인접 리스트&lt;/span&gt; 사용&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;PQ&lt;/span&gt;로&amp;nbsp;최소&amp;nbsp;cost&amp;nbsp;뽑으면서&amp;nbsp;정점을&amp;nbsp;방문하여&amp;nbsp;최단&amp;nbsp;거리&amp;nbsp;갱신&lt;/li&gt;
&lt;li&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;필요)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;343&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt6gZx/btsI5qWmdmd/G2a8SoIK3NsAPAoOQJkOPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt6gZx/btsI5qWmdmd/G2a8SoIK3NsAPAoOQJkOPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt6gZx/btsI5qWmdmd/G2a8SoIK3NsAPAoOQJkOPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt6gZx%2FbtsI5qWmdmd%2FG2a8SoIK3NsAPAoOQJkOPK%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;700&quot; height=&quot;343&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;343&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;동작 원리&lt;/b&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;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;시작 정점을 선택하고, 이 정점에서 다른 모든 정점으로의 최단 거리를 저장할 배열을 초기화한다. 시작 정점의 거리는 0으로 설정하고, 나머지 정점의 거리는 무한대로 설정한다.&lt;/li&gt;
&lt;/ul&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;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;/li&gt;
&lt;li&gt;&lt;b&gt;모든 정점을 방문할 때까지 반복한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&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;Node 클래스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정점의 번호와 해당 정점까지의 비용을 포함한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Comparable 인터페이스를 구현하여 우선순위 큐에서 최소 비용의 정점이 먼저 나오도록 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1723781279518&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static class Node implements Comparable&amp;lt;Node&amp;gt; {
    int dest;
    int cost;

    public Node(int dest, int cost) {
        this.dest = dest;
        this.cost = cost;
    }

    @Override
    public int compareTo(Node o) {
        return Integer.compare(this.cost, o.cost);
    }
}&lt;/code&gt;&lt;/pre&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;pre id=&quot;code_1723781166451&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void dijkstra(int start) {
    PriorityQueue&amp;lt;Node&amp;gt; pq = new PriorityQueue&amp;lt;&amp;gt;();

    Arrays.fill(dist, Integer.MAX_VALUE);
    dist[start] = 0;
    // 시작점: 1번 노드
    pq.offer(new Node(start, 0));

    while (!pq.isEmpty()) {
        Node current = pq.poll();

        // 목적지 노드가 이미 방문했던 정점이면 다시 방문하지 않는다
        // 첫번째 방문에서 최단거리가 결정되기 때문
        if (visited[current.dest]) {
            continue;
        }
        // 방문처리
        visited[current.dest] = true;

        for (Node next : adjList[current.dest]) {
            if (dist[next.dest] &amp;gt; next.cost + current.cost) {
                dist[next.dest] = next.cost + current.cost;
                pq.offer(new Node(next.dest, dist[next.dest]));
            }
        }
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;예제 문제&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;백준 1753번 : 최단경로&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1753&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1753&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1723789367797&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[코테] 백준 1753번 : 최단경로 (java)&quot; data-og-description=&quot;https://www.acmicpc.net/problem/1753알고리즘 분류 : 그래프 이론, 데이크스트라, 최단&amp;nbsp;경로❓문제 해석음이 아닌 가중 그래프에서의 단일 쌍, 단일 출발, 단일 도착 최단 경로 문제에서는 다익스트라 &quot; data-og-host=&quot;steady-record.tistory.com&quot; data-og-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-1753%EB%B2%88-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-java&quot; data-og-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-1753%EB%B2%88-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-java&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/du5S96/hyWSn3Kruw/Zg2VtWPdkDTU4W9LewBzw0/img.png?width=800&amp;amp;height=488&amp;amp;face=0_0_800_488,https://scrap.kakaocdn.net/dn/cvccdc/hyWSawzujK/fQckStFjtQxh4k5bc4Xqlk/img.png?width=800&amp;amp;height=488&amp;amp;face=0_0_800_488,https://scrap.kakaocdn.net/dn/biQdh0/hyWOqVpfJX/zMjQMYXKu0xgGVArHT5hKk/img.png?width=1148&amp;amp;height=321&amp;amp;face=0_0_1148_321&quot;&gt;&lt;a href=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-1753%EB%B2%88-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-1753%EB%B2%88-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-java&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/du5S96/hyWSn3Kruw/Zg2VtWPdkDTU4W9LewBzw0/img.png?width=800&amp;amp;height=488&amp;amp;face=0_0_800_488,https://scrap.kakaocdn.net/dn/cvccdc/hyWSawzujK/fQckStFjtQxh4k5bc4Xqlk/img.png?width=800&amp;amp;height=488&amp;amp;face=0_0_800_488,https://scrap.kakaocdn.net/dn/biQdh0/hyWOqVpfJX/zMjQMYXKu0xgGVArHT5hKk/img.png?width=1148&amp;amp;height=321&amp;amp;face=0_0_1148_321');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[코테] 백준 1753번 : 최단경로 (java)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://www.acmicpc.net/problem/1753알고리즘 분류 : 그래프 이론, 데이크스트라, 최단&amp;nbsp;경로❓문제 해석음이 아닌 가중 그래프에서의 단일 쌍, 단일 출발, 단일 도착 최단 경로 문제에서는 다익스트라&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;steady-record.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;벨만-포드 알고리즘 (Bellman-Ford Algorithm)&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가중&amp;nbsp;그래프에서의&amp;nbsp;단일&amp;nbsp;쌍,&amp;nbsp;단일&amp;nbsp;출발,&amp;nbsp;단일&amp;nbsp;도착&amp;nbsp;최단&amp;nbsp;경로&amp;nbsp;문제&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;음수의&amp;nbsp;간선&lt;/span&gt;을&amp;nbsp;포함&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;음수의&amp;nbsp;사이클&lt;/span&gt;이&amp;nbsp;존재할&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp; &lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;V-1번&amp;nbsp;탐색하여&amp;nbsp;최단&amp;nbsp;거리를&amp;nbsp;구하고&amp;nbsp;V번&amp;nbsp;구했을&amp;nbsp;때,&amp;nbsp;최단거리&amp;nbsp;갱신이&amp;nbsp;된다면,&amp;nbsp;음수의&amp;nbsp;사이클이&amp;nbsp;존재한다는&amp;nbsp;것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;케이스가&amp;nbsp;3000&amp;nbsp;~&amp;nbsp;5000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rURxK/btsI7eG0zrq/qSVNwDYg2Tu8M59R9T32lK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rURxK/btsI7eG0zrq/qSVNwDYg2Tu8M59R9T32lK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rURxK/btsI7eG0zrq/qSVNwDYg2Tu8M59R9T32lK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrURxK%2FbtsI7eG0zrq%2FqSVNwDYg2Tu8M59R9T32lK%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;700&quot; height=&quot;405&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;동작원리&lt;/b&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;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;시작 정점의 거리를 0으로 설정하고, 나머지 모든 정점의 거리를 무한대로 설정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;거리 갱신&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 간선에 대해 V-1번 반복해서 간선의 시작 정점에서 도착 정점으로 가는 경로가 현재 알려진 경로보다 짧다면, 그 경로를 갱신한다.&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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;Edge 클래스&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1723789498534&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static class Edge{
    int from;
    int to;
    int cost;

    public Edge(int from, int to, int cost){
        this.from = from;
        this.to = to;
        this.cost = cost;
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드 구현&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1723789528304&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static boolean bellmanFordMoore(int V, int start){
    Arrays.fill(dist, Long.MAX_VALUE);
    dist[start] = 0;

    // V-1번 E개의 모든 간선 확인
    for(int i=0; i&amp;lt;V-1; i++){
        for(Edge edge : adjList){
            // 간선의 시작점이 아직 탐색 불가면 continue
            if(dist[edge.from] == Long.MAX_VALUE){
                continue;
            }

            // 최단거리 갱신
            if(dist[edge.to] &amp;gt; dist[edge.from] + edge.cost){
                dist[edge.to] = dist[edge.from] + edge.cost;
            }
        }
    }

    boolean isNegativeCycle = false;
    // V번째 E개의 모든 간선을 확인해서 갱신되는 구간이 있으면 음의 사이클이 존재하는 것
    for(Edge edge : adjList){
        if(dist[edge.from] == Long.MAX_VALUE){
            continue;
        }

        if(dist[edge.to] &amp;gt; dist[edge.from] + edge.cost){
            isNegativeCycle = true;
            break;
        }
    }

    return isNegativeCycle;
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;예제 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;백준 11657번 : 타임 머신&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11657&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/11657&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 풀이&lt;/p&gt;
&lt;figure id=&quot;og_1723795281840&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[코테] 백준 11657번 : 타임 머신 (java)&quot; data-og-description=&quot;https://www.acmicpc.net/problem/11657알고리즘 분류 : 그래프 이론, 최단 경로, 벨만&amp;ndash;포드❓문제&amp;nbsp; 해석&amp;nbsp;1. 거리 초기화 시작&amp;nbsp;정점의&amp;nbsp;거리를&amp;nbsp;0으로&amp;nbsp;설정하고,&amp;nbsp;나머지&amp;nbsp;모든&amp;nbsp;정점의&amp;nbsp;거리를&amp;nbsp;무한대&quot; data-og-host=&quot;steady-record.tistory.com&quot; data-og-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-11657%EB%B2%88-%ED%83%80%EC%9E%84-%EB%A8%B8%EC%8B%A0-java&quot; data-og-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-11657%EB%B2%88-%ED%83%80%EC%9E%84-%EB%A8%B8%EC%8B%A0-java&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b3Pbw4/hyWOe1IQyM/LkrcRW3qMDTkeKazMGPcFk/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/b3aKSQ/hyWOe1IQCS/TVAduWOwseG1FXBOBi6DR1/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/lqLNv/hyWSoawZwb/KJTrhySpmPjI5ndZIB4Mp1/img.png?width=1147&amp;amp;height=773&amp;amp;face=0_0_1147_773&quot;&gt;&lt;a href=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-11657%EB%B2%88-%ED%83%80%EC%9E%84-%EB%A8%B8%EC%8B%A0-java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-11657%EB%B2%88-%ED%83%80%EC%9E%84-%EB%A8%B8%EC%8B%A0-java&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b3Pbw4/hyWOe1IQyM/LkrcRW3qMDTkeKazMGPcFk/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/b3aKSQ/hyWOe1IQCS/TVAduWOwseG1FXBOBi6DR1/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/lqLNv/hyWSoawZwb/KJTrhySpmPjI5ndZIB4Mp1/img.png?width=1147&amp;amp;height=773&amp;amp;face=0_0_1147_773');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[코테] 백준 11657번 : 타임 머신 (java)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://www.acmicpc.net/problem/11657알고리즘 분류 : 그래프 이론, 최단 경로, 벨만&amp;ndash;포드❓문제&amp;nbsp; 해석&amp;nbsp;1. 거리 초기화 시작&amp;nbsp;정점의&amp;nbsp;거리를&amp;nbsp;0으로&amp;nbsp;설정하고,&amp;nbsp;나머지&amp;nbsp;모든&amp;nbsp;정점의&amp;nbsp;거리를&amp;nbsp;무한대&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;steady-record.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;플로이드-워셜 알고리즘 (Floyd-Warshall&amp;nbsp;Algorithm)&amp;nbsp;&lt;/b&gt;&lt;/h2&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;background-color: #f6e199;&quot;&gt;전체&amp;nbsp;쌍&lt;/span&gt;&amp;nbsp;최단&amp;nbsp;경로&amp;nbsp;문제&lt;/li&gt;
&lt;li&gt;케이스가&amp;nbsp;300&amp;nbsp;~&amp;nbsp;500&lt;/li&gt;
&lt;li&gt;그래프에서&amp;nbsp;음수&amp;nbsp;가중치의&amp;nbsp;간선이&amp;nbsp;존재할&amp;nbsp;수&amp;nbsp;있지만,&amp;nbsp;음수&amp;nbsp;사이클(negative&amp;nbsp;cycle)은&amp;nbsp;없어야&amp;nbsp;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZ1dSa/btsI7iWQUqm/Ugy0y12IEWWW5kwdAlVFOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZ1dSa/btsI7iWQUqm/Ugy0y12IEWWW5kwdAlVFOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZ1dSa/btsI7iWQUqm/Ugy0y12IEWWW5kwdAlVFOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZ1dSa%2FbtsI7iWQUqm%2FUgy0y12IEWWW5kwdAlVFOK%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;700&quot; height=&quot;366&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;동작 원리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플로이드-워셜 알고리즘은 동적 프로그래밍(Dynamic Programming)을 기반으로 하며, 점진적으로 모든 정점 간의 최단 경로를 계산한다. 이 알고리즘의 핵심 아이디어는 &quot;&lt;u&gt;중간에 다른 정점을 거치는 경로가 직접 연결된 경로보다 더 짧을 수 있다&lt;/u&gt;&quot;는 점이다.&lt;br /&gt;&lt;br /&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;&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그래프의 인접 행렬(Adjacency Matrix)로 초기화한다. 만약 두 정점 간에 직접 연결된 간선이 있다면 그 가중치로 초기화하고, 연결되어 있지 않다면 무한대(또는 매우 큰 값)로 설정한다. 자신에게 가는 거리는 0으로 설정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동적 프로그래밍(DP) 적용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 정점을 중간 정점으로 고려하여, 다른 모든 정점 쌍에 대해 최단 경로를 갱신한다. 즉, 정점 k를 중간 정점으로 사용하는 경우, i에서 j로 가는 경로가 i -&amp;gt; k -&amp;gt; j로 더 짧아질 수 있는지 확인하고, 그렇다면 경로를 갱신한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 출력 :&lt;/b&gt; 모든 정점 쌍 간의 최단 경로가 담긴 행렬을 출력합니다.&lt;/li&gt;
&lt;/ol&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;pre id=&quot;code_1723795792825&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void floydWarshall(){
    for(int k=1; k&amp;lt;=N; k++){
        for(int i=1; i&amp;lt;=N; i++){
            for(int j=1; j&amp;lt;=N; j++){
                // k를 거쳐가는 비용이 INF인 경우 못가는 곳이라 의미없음(오버플로우 방지용)
                if(dist[i][k] == INF || dist[k][j] == INF){
                    continue;
                }
                // i-&amp;gt;j 보다 i-&amp;gt;k-&amp;gt;j가 작으면 갱신
                dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;예제 문제&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;백준&amp;nbsp;2458번&amp;nbsp;:&amp;nbsp;키&amp;nbsp;순서&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2458&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/2458&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1723799302559&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[코테] 백준 2458번 : 키 순서 (java)&quot; data-og-description=&quot;https://www.acmicpc.net/problem/2458알고리즘 분류 : 그래프 이론, 그래프 탐색, 깊이 우선 탐색, 최단 경로, 플로이드&amp;ndash;워셜❓문제 해석모든 학생의 키를 비교한 횟수를 알아야하기 때문에 전체 쌍의 &quot; data-og-host=&quot;steady-record.tistory.com&quot; data-og-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-2458%EB%B2%88-%ED%82%A4-%EC%88%9C%EC%84%9C-java&quot; data-og-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-2458%EB%B2%88-%ED%82%A4-%EC%88%9C%EC%84%9C-java&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bu9s3G/hyWOk1VFDs/PMc3wUrlSHVBhSUXHntghK/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/garwy/hyWSkMKzAH/FAMddurRZCZ5T8wzHDWxm0/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/erE0pm/hyWShvIulo/9ZDH6qgaszqqybi8DZS540/img.png?width=1148&amp;amp;height=866&amp;amp;face=0_0_1148_866&quot;&gt;&lt;a href=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-2458%EB%B2%88-%ED%82%A4-%EC%88%9C%EC%84%9C-java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-2458%EB%B2%88-%ED%82%A4-%EC%88%9C%EC%84%9C-java&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bu9s3G/hyWOk1VFDs/PMc3wUrlSHVBhSUXHntghK/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/garwy/hyWSkMKzAH/FAMddurRZCZ5T8wzHDWxm0/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/erE0pm/hyWShvIulo/9ZDH6qgaszqqybi8DZS540/img.png?width=1148&amp;amp;height=866&amp;amp;face=0_0_1148_866');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[코테] 백준 2458번 : 키 순서 (java)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://www.acmicpc.net/problem/2458알고리즘 분류 : 그래프 이론, 그래프 탐색, 깊이 우선 탐색, 최단 경로, 플로이드&amp;ndash;워셜❓문제 해석모든 학생의 키를 비교한 횟수를 알아야하기 때문에 전체 쌍의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;steady-record.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>bellman-ford</category>
      <category>Dijkstra</category>
      <category>Floyd-warshall</category>
      <category>다익스트라</category>
      <category>벨만-포드</category>
      <category>플로이드-워셜</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/278</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%82%BC%EC%84%B1SDS-24%EB%85%84-%ED%95%98%EB%B0%98%EA%B8%B0-%EB%8C%80%ED%95%99%EC%83%9D-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%8A%B9%EA%B0%95Day9-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%8B%A4%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%9D%BC-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%ED%94%8C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9B%8C%EC%85%9C#entry278comment</comments>
      <pubDate>Fri, 16 Aug 2024 18:08:46 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 백준 2458번 : 키 순서 (java)</title>
      <link>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-2458%EB%B2%88-%ED%82%A4-%EC%88%9C%EC%84%9C-java</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2458&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/2458&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;알고리즘 분류 : 그래프 이론, 그래프 탐색, 깊이 우선 탐색, 최단 경로, 플로이드&amp;ndash;워셜&lt;/b&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❓문제&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;866&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xuT6F/btsI6VHAbI2/KuKw8GHGh6FKPuYG0lzX31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xuT6F/btsI6VHAbI2/KuKw8GHGh6FKPuYG0lzX31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xuT6F/btsI6VHAbI2/KuKw8GHGh6FKPuYG0lzX31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxuT6F%2FbtsI6VHAbI2%2FKuKw8GHGh6FKPuYG0lzX31%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;1148&quot; height=&quot;866&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;866&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1149&quot; data-origin-height=&quot;435&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5hgTG/btsI7f6UW3V/xWrkRXG8v5u1FC4mZbu6o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5hgTG/btsI7f6UW3V/xWrkRXG8v5u1FC4mZbu6o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5hgTG/btsI7f6UW3V/xWrkRXG8v5u1FC4mZbu6o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5hgTG%2FbtsI7f6UW3V%2FxWrkRXG8v5u1FC4mZbu6o1%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;1149&quot; height=&quot;435&quot; data-origin-width=&quot;1149&quot; data-origin-height=&quot;435&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;843&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N8ZUu/btsI6TXupqG/4cvq1C2e8agbkDkutjzQZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N8ZUu/btsI6TXupqG/4cvq1C2e8agbkDkutjzQZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N8ZUu/btsI6TXupqG/4cvq1C2e8agbkDkutjzQZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN8ZUu%2FbtsI6TXupqG%2F4cvq1C2e8agbkDkutjzQZK%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;1157&quot; height=&quot;843&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;843&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; 해석&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 학생의 키를 비교한 횟수를 알아야하기 때문에 전체 쌍의 계산이 필요한 &quot;플로이드-워셜&quot; 알고리즘을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 거리 초기화&amp;nbsp;&lt;/b&gt; &lt;br /&gt;만약 두 정점 간에 직접 연결된 간선이 있다면 그 가중치로 초기화하고, 연결되어 있지 않다면 무한대(또는 매우 큰 값)로 설정한다. 자신에게 가는 거리는 0으로 설정한다.&lt;/p&gt;
&lt;pre id=&quot;code_1723798760405&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (int n = 1; n &amp;lt;= N; n++) {
    Arrays.fill(map[n], INF);
    map[n][n] = 0;
}&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;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;2. 동적 프로그래밍(DP) 적용&lt;/b&gt; &lt;br /&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;k를&amp;nbsp;중간&amp;nbsp;정점으로&amp;nbsp;사용하는&amp;nbsp;경우,&amp;nbsp;i에서&amp;nbsp;j로&amp;nbsp;가는&amp;nbsp;경로가&amp;nbsp;i&amp;nbsp;-&amp;gt;&amp;nbsp;k&amp;nbsp;-&amp;gt;&amp;nbsp;j로&amp;nbsp;더&amp;nbsp;짧아질&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;확인하고,&amp;nbsp;그렇다면&amp;nbsp;경로를&amp;nbsp;갱신한다.&lt;/p&gt;
&lt;pre id=&quot;code_1723798774999&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static void floyd() {
    for (int k = 1; k &amp;lt;= N; k++) {
        for (int a = 1; a &amp;lt;= N; a++) {
            for (int b = 1; b &amp;lt;= N; b++) {
                if (a == b)
                    continue;
                if (map[a][k] == INF || map[k][b] == INF)
                    continue;

                map[a][b] = Math.min(map[a][b], map[a][k] + map[k][b]);
            }
        }
    }
}&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;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;3. 결과 출력&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bceTGx/btsI7jao0Zz/33hYFBblG1ekv8wTCI1nl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bceTGx/btsI7jao0Zz/33hYFBblG1ekv8wTCI1nl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bceTGx/btsI7jao0Zz/33hYFBblG1ekv8wTCI1nl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbceTGx%2FbtsI7jao0Zz%2F33hYFBblG1ekv8wTCI1nl1%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;700&quot; height=&quot;264&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 출력해보면 위와 같은 테이블이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행을 보면 해당 행보다 큰 학생의 수를 알 수 있고, 열을 보면 해당 열보다 작은 학생의 수를 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신보다 큰 학생과 작은 학생의 수가 N - 1(자기자신) 와 일치한다면 자신의 키 순서를 알 수 있는 학생이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;⭕정답 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1695559028389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	
	static final int INF = Integer.MAX_VALUE;
	
	static int N, M;
	static int[][] map;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
	
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
	
		map = new int[N + 1][N + 1];
		
		for (int n = 1; n &amp;lt;= N; n++) {
			Arrays.fill(map[n], INF);
			map[n][n] = 0;
		}
		
		// map 생성
		int a, b;
		for (int m = 0; m &amp;lt; M; m++) {
			st = new StringTokenizer(br.readLine());
			a = Integer.parseInt(st.nextToken());
			b = Integer.parseInt(st.nextToken());
			
			map[a][b] = 1;
		}
		
		floyd();
		
		int answer = 0;
		for (int i = 1; i &amp;lt;= N; i++) {
			int count = 0;
			for (int j = 1; j &amp;lt;= N; j++) { 
				if (i == j) continue;
				
				if (map[i][j] != INF || map[j][i] != INF) {
					count++;
				}
			}
			// 자기자신을 제외한 N-1개의 노드와 키순서를 알면 자신의 키가 몇번째인지 알 수 있다.
            if(count == N-1){
                answer++;
            }
		}
		System.out.println(answer);
		
		br.close();
	}

	private static void floyd() {
		
		for (int k = 1; k &amp;lt;= N; k++) {
			for (int a = 1; a &amp;lt;= N; a++) {
				for (int b = 1; b &amp;lt;= N; b++) {
					if (a == b) continue;
					if (map[a][k] == INF || map[k][b] == INF) continue;
					
					//if (k == a || k == b) continue;
					map[a][b] = Math.min(map[a][b], map[a][k] + map[k][b]);
				}
			}
		}
	}

}&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;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❗결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z21j0/btsI6MdcRhW/yZToCyKnafeHunkOPW5lt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z21j0/btsI6MdcRhW/yZToCyKnafeHunkOPW5lt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z21j0/btsI6MdcRhW/yZToCyKnafeHunkOPW5lt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ21j0%2FbtsI6MdcRhW%2FyZToCyKnafeHunkOPW5lt1%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;800&quot; height=&quot;56&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩테스트/백준</category>
      <category>그래프 이론</category>
      <category>그래프 탐색</category>
      <category>깊이 우선 탐색</category>
      <category>최단 경로</category>
      <category>플로이드&amp;ndash;워셜</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/277</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-2458%EB%B2%88-%ED%82%A4-%EC%88%9C%EC%84%9C-java#entry277comment</comments>
      <pubDate>Fri, 16 Aug 2024 18:08:03 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 백준 11657번 : 타임 머신 (java)</title>
      <link>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-11657%EB%B2%88-%ED%83%80%EC%9E%84-%EB%A8%B8%EC%8B%A0-java</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11657&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/11657&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;알고리즘 분류 : 그래프 이론, 최단 경로, 벨만&amp;ndash;포드&lt;/b&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❓문제&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1147&quot; data-origin-height=&quot;773&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUNhlO/btsI6O2NLat/o60G8CskjRjleyAsffiED1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUNhlO/btsI6O2NLat/o60G8CskjRjleyAsffiED1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUNhlO/btsI6O2NLat/o60G8CskjRjleyAsffiED1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUNhlO%2FbtsI6O2NLat%2Fo60G8CskjRjleyAsffiED1%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;1147&quot; height=&quot;773&quot; data-origin-width=&quot;1147&quot; data-origin-height=&quot;773&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOJDSj/btsI6S47L9V/RmNemQiwK0y9pl1yHegIl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOJDSj/btsI6S47L9V/RmNemQiwK0y9pl1yHegIl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOJDSj/btsI6S47L9V/RmNemQiwK0y9pl1yHegIl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOJDSj%2FbtsI6S47L9V%2FRmNemQiwK0y9pl1yHegIl1%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;1151&quot; height=&quot;697&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;697&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; 해석&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 거리 초기화&lt;/b&gt; &lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;시작&amp;nbsp;정점의&amp;nbsp;거리를&amp;nbsp;0으로&amp;nbsp;설정하고,&amp;nbsp;나머지&amp;nbsp;모든&amp;nbsp;정점의&amp;nbsp;거리를&amp;nbsp;무한대로&amp;nbsp;설정한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;54&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IVuNE/btsI7dHXwin/oIGBpCUjMKTMBChKaJVhcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IVuNE/btsI7dHXwin/oIGBpCUjMKTMBChKaJVhcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IVuNE/btsI7dHXwin/oIGBpCUjMKTMBChKaJVhcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIVuNE%2FbtsI7dHXwin%2FoIGBpCUjMKTMBChKaJVhcK%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;400&quot; height=&quot;54&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;54&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 거리 갱신&lt;/b&gt; &lt;br /&gt;모든&amp;nbsp;간선에&amp;nbsp;대해&amp;nbsp;V-1번&amp;nbsp;반복해서&amp;nbsp;간선의&amp;nbsp;시작&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nNi0Z/btsI4YMFd2W/knfWK9c7JejmKGDIwh1lT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nNi0Z/btsI4YMFd2W/knfWK9c7JejmKGDIwh1lT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nNi0Z/btsI4YMFd2W/knfWK9c7JejmKGDIwh1lT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnNi0Z%2FbtsI4YMFd2W%2FknfWK9c7JejmKGDIwh1lT1%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;600&quot; height=&quot;195&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dist[from] &amp;gt; dist[to] + edge.cost 이므로 dist 업데이트를 한다.&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-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8KtlE/btsI5MSe5X6/xCz27kUmW7aICMPa6tAxA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8KtlE/btsI5MSe5X6/xCz27kUmW7aICMPa6tAxA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8KtlE/btsI5MSe5X6/xCz27kUmW7aICMPa6tAxA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8KtlE%2FbtsI5MSe5X6%2FxCz27kUmW7aICMPa6tAxA0%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;600&quot; height=&quot;195&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dist[from] &amp;gt; dist[to] + edge.cost 이므로 dist 업데이트를 한다.&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-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bETnQn/btsI5eoe6Nf/1kNz0SwgblK5FWYtjn1mT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bETnQn/btsI5eoe6Nf/1kNz0SwgblK5FWYtjn1mT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bETnQn/btsI5eoe6Nf/1kNz0SwgblK5FWYtjn1mT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbETnQn%2FbtsI5eoe6Nf%2F1kNz0SwgblK5FWYtjn1mT1%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;600&quot; height=&quot;195&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dist[from] == dist[to] + edge.cost 이므로 dist 업데이트 되지 않는다.&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-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNDuMQ/btsI7ioSdF4/oWBy8wvBxBLkFEKQyp10H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNDuMQ/btsI7ioSdF4/oWBy8wvBxBLkFEKQyp10H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNDuMQ/btsI7ioSdF4/oWBy8wvBxBLkFEKQyp10H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNDuMQ%2FbtsI7ioSdF4%2FoWBy8wvBxBLkFEKQyp10H1%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;600&quot; height=&quot;195&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dist[from] &amp;lt; dist[to] + edge.cost 이므로 dist 업데이트 되지 않는다.&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;이렇게 (V - 1) * E 번 반복하여 거리 계산을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 음수 사이클 검출&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 모든 간선에 대해 추가로 한 번 더 거리 갱신을 한다. 이 과정에서 최단 거리 갱신이 되면, 음수 사이클이 존재한다고 판단할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 테스트케이스의 경우, 음수 사이클이 존재하지 않는다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;⭕정답 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1695559028389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	static class Edge {
		int from;
		int to;
		int cost;

		public Edge(int from, int to, int cost) {
			this.from = from;
			this.to = to;
			this.cost = cost;
		}
	}

	static long[] dist;
	static ArrayList&amp;lt;Edge&amp;gt; adjList;

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());

		dist = new long[N + 1];
		adjList = new ArrayList&amp;lt;&amp;gt;();

		int A, B, C;
		for (int m = 0; m &amp;lt; M; m++) {
			st = new StringTokenizer(br.readLine());
			A = Integer.parseInt(st.nextToken());
			B = Integer.parseInt(st.nextToken());
			C = Integer.parseInt(st.nextToken());

			adjList.add(new Edge(A, B, C));
		}

		StringBuilder sb = new StringBuilder();
		if (bellmanFordMoore(N, 1)) {
			sb.append(&quot;-1\n&quot;);
		} else {
			for (int i = 2; i &amp;lt;= N; i++) {
				if (dist[i] == Long.MAX_VALUE) {
					sb.append(&quot;-1\n&quot;);
				} else {
					sb.append(dist[i]).append(&quot;\n&quot;);
				}
			}
		}
		bw.write(sb.toString());
		bw.flush();
		bw.close();
		br.close();
	}

	static boolean bellmanFordMoore(int V, int start) {
		Arrays.fill(dist, Long.MAX_VALUE);
		dist[start] = 0;

		// V-1번 E개의 모든 간선 확인
		for (int i = 0; i &amp;lt; V - 1; i++) {
			for (Edge edge : adjList) {
				// 간선의 시작점이 아직 탐색 불가면 continue
				if (dist[edge.from] == Long.MAX_VALUE) {
					continue;
				}

				// 최단거리 갱신
				if (dist[edge.to] &amp;gt; dist[edge.from] + edge.cost) {
					dist[edge.to] = dist[edge.from] + edge.cost;
				}
			}
		}

		boolean isNegativeCycle = false;
		// V번째 E개의 모든 간선을 확인해서 갱신되는 구간이 있으면 음의 사이클이 존재하는 것
		for (Edge edge : adjList) {
			if (dist[edge.from] == Long.MAX_VALUE) {
				continue;
			}

			if (dist[edge.to] &amp;gt; dist[edge.from] + edge.cost) {
				isNegativeCycle = true;
				break;
			}
		}

		return isNegativeCycle;
	}
}&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;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;❗결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JZDD2/btsI5XM5l11/GqZ6AR2D1z3Y8OgtSWS1x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JZDD2/btsI5XM5l11/GqZ6AR2D1z3Y8OgtSWS1x1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JZDD2/btsI5XM5l11/GqZ6AR2D1z3Y8OgtSWS1x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJZDD2%2FbtsI5XM5l11%2FGqZ6AR2D1z3Y8OgtSWS1x1%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;800&quot; height=&quot;50&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩테스트/백준</category>
      <category>그래프 이론</category>
      <category>벨만&amp;ndash;포드</category>
      <category>최단 경로</category>
      <author>developer of the night sky</author>
      <guid isPermaLink="true">https://steady-record.tistory.com/276</guid>
      <comments>https://steady-record.tistory.com/entry/%EC%BD%94%ED%85%8C-%EB%B0%B1%EC%A4%80-11657%EB%B2%88-%ED%83%80%EC%9E%84-%EB%A8%B8%EC%8B%A0-java#entry276comment</comments>
      <pubDate>Fri, 16 Aug 2024 17:01:10 +0900</pubDate>
    </item>
  </channel>
</rss>