<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ESTP 하고재비로 살아가기</title>
    <link>https://devpanda.tistory.com/</link>
    <description>let's learn and roll!</description>
    <language>ko</language>
    <pubDate>Thu, 16 Apr 2026 09:20:49 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>대왕판다</managingEditor>
    <image>
      <title>ESTP 하고재비로 살아가기</title>
      <url>https://tistory1.daumcdn.net/tistory/4704806/attach/a74510cdc3d64e45b1402cc095aa732c</url>
      <link>https://devpanda.tistory.com</link>
    </image>
    <item>
      <title>TCP/IP 4계층과 OSI 7계층, 전송 계층의 handshake</title>
      <link>https://devpanda.tistory.com/99</link>
      <description>&lt;h1&gt;기본용어&lt;/h1&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;트래픽 (Traffic):&lt;/b&gt; 네트워크 상에서 데이터가 이동하는 양. 트래픽은 인터넷 사용자의 수, 웹 사이트의 인기도, 서비스의 사용량 등에 따라 변동될 수 있음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대역폭 (Bandwidth):&lt;/b&gt; 네트워크가 한 번에 전송할 수 있는 데이터의 양(초당 전송 속도) 일반적으로 초당 비트(bit) 또는 바이트(Byte) 단위로 측정 (배관의 파이프 크기)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;처리량 (Throughput):&lt;/b&gt; 네트워크에서 초당 실제로 처리되는 패킷의 양을 나타내는 실용적인 지표 (실제 파이프 속 흐르는 물의 양)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전송계층의 3-way handshake (연결 수립)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OjOTu/btsdGGO7U2M/Jt1T8rtNQg9xmMsBWKpra0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OjOTu/btsdGGO7U2M/Jt1T8rtNQg9xmMsBWKpra0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OjOTu/btsdGGO7U2M/Jt1T8rtNQg9xmMsBWKpra0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOjOTu%2FbtsdGGO7U2M%2FJt1T8rtNQg9xmMsBWKpra0%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;2386&quot; height=&quot;1491&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-way handshake (연결 해제)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled 1.png&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x0LwF/btsdJh1R6Tw/Ll0qUdDOTH43WvBzHAYPz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x0LwF/btsdJh1R6Tw/Ll0qUdDOTH43WvBzHAYPz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x0LwF/btsdJh1R6Tw/Ll0qUdDOTH43WvBzHAYPz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx0LwF%2FbtsdJh1R6Tw%2FLl0qUdDOTH43WvBzHAYPz0%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;2386&quot; height=&quot;1491&quot; data-filename=&quot;Untitled 1.png&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FIN &amp;rarr; 더 이상 보낸 데이터가 없음을 의미&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;Graceful connection release(정상적인 연결 해제&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;정상적인 연결 해제에서는 양쪽이 커넥션이 서로 모두 커넥션을 닫을 때까지 연결되어 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Abrupt connection release(갑작스런 연결 해제&lt;/b&gt;)
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;갑자기 한 TCP 엔티티가 연결을 강제로 닫는 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RST 패킷 수신, 타임아웃, 지속적인 재전송 실패, ICMP 에러 메시지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;한 사용자가 두 데이터 전송 방향을 모두 닫는 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OSI 7계층&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled 2.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2j1nW/btsdGAIqBx0/9GT6lt0GQkOy1fseIuPl1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2j1nW/btsdGAIqBx0/9GT6lt0GQkOy1fseIuPl1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2j1nW/btsdGAIqBx0/9GT6lt0GQkOy1fseIuPl1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2j1nW%2FbtsdGAIqBx0%2F9GT6lt0GQkOy1fseIuPl1k%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;355&quot; data-filename=&quot;Untitled 2.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;355&quot;/&gt;&lt;/span&gt;&lt;/figure&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;응용 계층 (Application Layer):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트는 웹 브라우저를 사용해 특정 홈페이지를 요청 이 때, HTTP 프로토콜이 사용되며, 클라이언트는 HTTP 요청 메시지를 생성합니다. 이 요청 메시지는 메소드(GET, POST 등), URI, 프로토콜 버전, 헤더 정보 및 본문 데이터(예: JSON)를 포함합니다.&lt;/li&gt;
&lt;li&gt;서버는 클라이언트의 요청을 처리하고, HTTP 응답 메시지를 생성합니다. 이 응답 메시지는 상태 코드(예: 200 OK), 프로토콜 버전, 헤더 정보 및 본문 데이터(예: JSON)를 포함합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표현 계층 (Presentation Layer):&lt;/b&gt; 표현 계층은 데이터 형식을 처리하고, 필요한 경우 암호화/복호화를 수행합니다. JSON과 같은 형식의 데이터는 이 계층에서 처리됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세션 계층 (Session Layer):&lt;/b&gt; 세션 계층은 클라이언트와 서버 간의 연결을 관리합니다. 즉, 세션을 생성, 유지 및 종료하는 역할을 담당합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전송 계층 (Transport Layer):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전송 계층은 클라이언트와 서버 간의 통신을 관리하며, 일반적으로 TCP 프로토콜을 사용합니다. HTTP 요청 메시지는 TCP 세그먼트로 나누어지고, 각 세그먼트는 목적지에 도달할 때까지 전송 계층에서 추적 및 관리됩니다.&lt;/li&gt;
&lt;li&gt;흐름 제어와 오류 처리를 담당하며, 필요한 경우 세그먼트의 재전송을 수행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네트워크 계층 (Network Layer):&lt;/b&gt; 네트워크 계층은 IP 프로토콜을 사용하여 데이터 패킷을 전송합니다. 이 계층에서는 패킷의 출발지와 목적지 IP 주소를 확인하고, 라우팅을 통해 최적의 경로를 선택하여 데이터를 전송합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 링크 계층 (Data Link Layer):&lt;/b&gt; 데이터 링크 계층은 물리 계층에서 전송되는 비트를 프레임으로 구성하고, 에러 검출 및 흐름 제어를 수행합니다. 이 계층에서는 MAC 주소를 사용하여 데이터를 전송합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;물리 계층 (Physical Layer):&lt;/b&gt; 물리 계층에서는 전기 신호로 변환된 데이터 비트를 실제로 전송합니다. 케이블, 무선 신호, 광섬유 등 다양한 매체를 통해 데이터가 전송됩니다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>개발/네트워크</category>
      <category>osi</category>
      <category>tcp</category>
      <category>계층</category>
      <category>네트워크</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/99</guid>
      <comments>https://devpanda.tistory.com/99#entry99comment</comments>
      <pubDate>Wed, 3 May 2023 09:33:55 +0900</pubDate>
    </item>
    <item>
      <title>[디자인패턴] 싱글톤 패턴, 팩토리 패턴</title>
      <link>https://devpanda.tistory.com/98</link>
      <description>&lt;h1&gt;의존성 주입과 싱글톤 패턴&lt;/h1&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;제 3자인 컨테이너가 객체 간의 의존성을 연결해주는 방식&lt;/b&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;그렇기에 모듈들을 쉽게 교체할 수 있다&amp;rarr;테스팅과 마이그레이션이 수월하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성 주입을 하지 않은 경우&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// 싱글톤 클래스
public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void doSomething() {
        // some code
    }
}

public class Client {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton.doSomething();

        // Singleton 객체에 의존하는 다른 객체 생성
        OtherClass otherClass = new OtherClass();
        otherClass.doSomethingElse();
    }
}

// 싱글톤 클래스에 의존하는 클래스
public class OtherClass {
    private Singleton singleton;

    public OtherClass() {
// 인스턴스를 직접 생성
        singleton = Singleton.getInstance();
    }

    public void doSomethingElse() {
        singleton.doSomething();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;위 코드에서는 &lt;b&gt;OtherClass&lt;/b&gt; 클래스에서 &lt;b&gt;Singleton&lt;/b&gt; 객체를 직접 &lt;b&gt;생성하는 코드가 중복&lt;/b&gt;되어 나타나고&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Singleton&lt;/b&gt; &lt;b&gt;객체의 생성 및 관리에 대한 책임&lt;/b&gt;이 &lt;b&gt;OtherClass&lt;/b&gt; 클래스로 넘어가게 되므로, 유지보수 및 확장성이 저하된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성 주입을 사용하는 경우&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Singleton {
    // same code
}

public class Client {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton.doSomething();

        // 생성자를 통해 의존성 주입
        OtherClass otherClass = new OtherClass(singleton);
        otherClass.doSomethingElse();
    }
}

public class OtherClass {
    private Singleton singleton;

    // 생성자를 통해 의존성 주입
    public OtherClass(Singleton singleton) {
        this.singleton = singleton;
    }

    public void doSomethingElse() {
        singleton.doSomething();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;**OtherClass**클래스에서 **Singleton**객체를 생성하지 않고, &lt;b&gt;생성자를 통해&lt;/b&gt; 의존성 주입을 받도록 변경&lt;/li&gt;
&lt;li&gt;객체의 생성/관리 책임이 &lt;b&gt;Client&lt;/b&gt; 클래스로 다시 돌아가므로 &lt;b&gt;유지보수 및 확장성이 개선&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;팩토리 패턴&lt;/h1&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;/li&gt;
&lt;li&gt;상위 클래스가 중요한 뼈대 결정 &amp;harr; 하위 클래스에서 객체 생성에 관한 구체적 내용 결정&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;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;b&gt;객체 생성 과정이 변경되더라도 클라이언트 코드에 영향을 미치지 않음&lt;/b&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;li&gt;이를 통해 &lt;b&gt;객체 생성을 일관성 있게 처리&lt;/b&gt;할 수 있으며 &lt;b&gt;유지보수 및 확장성이 개선&lt;/b&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;pre class=&quot;java&quot;&gt;&lt;code&gt;public interface Animal {
    void makeSound();
}

public class Client {
    public static void main(String[] args) {
// dog 객체를 직접 생성
        Animal dog = new Dog();
        dog.makeSound();
    }
}

public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println(&quot;Bark!&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public interface Animal {
    void makeSound();
}

public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println(&quot;Bark!&quot;);
    }
}

public class AnimalFactory {
    public static Animal createAnimal(String type) {
        switch (type) {
            case &quot;dog&quot;:
                return new Dog();
            default:
                // some code
        }
    }
}

public class Client {
    public static void main(String[] args) {
// 애니멀팩토리를 이용해 객체 생성
        Animal dog = AnimalFactory.createAnimal(&quot;dog&quot;);
        dog.makeSound();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/객체지향개발</category>
      <category>객체지향개발</category>
      <category>디자인패턴</category>
      <category>싱글톤</category>
      <category>패턴</category>
      <category>팩토리</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/98</guid>
      <comments>https://devpanda.tistory.com/98#entry98comment</comments>
      <pubDate>Wed, 12 Apr 2023 23:09:51 +0900</pubDate>
    </item>
    <item>
      <title>Git 사용중 로컬-원격 저장소간 충돌상황일때(변경 사항이 충돌하지 않을때)</title>
      <link>https://devpanda.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;깃허브 레포지토리에서 리드미를 수정하고, 이를 fetch 혹은 pull 하지 않은 상태로,&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 즉 로컬에서 원격 저장소의 변경 내역을 업데이트하지 않은 상태로 새로운 커밋을 남겼다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 로컬저장소 변경 내역을 원격 저장소로 보내려하니 아래와 같은 에러가 발생했다.&lt;/p&gt;
&lt;pre id=&quot;code_1678977250685&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; git push origin main
 

To https://github.com/yongwoo-jeong/community-bulletin-board-MPA
 ! [rejected]        main -&amp;gt; main (fetch first)
error: 레퍼런스를 'https://github.com/yongwoo-jeong/community-bulletin-board-MPA'에 푸시하는데 실패했습니다
힌트: 리모트에 로컬에 없는 사항이 들어 있으므로 업데이트가
힌트: 거부되었습니다. 이 상황은 보통 또 다른 저장소에서 같은
힌트: 저장소로 푸시할 때 발생합니다.  푸시하기 전에
힌트: ('git pull ...' 등 명령으로) 리모트 변경 사항을 먼저
힌트: 포함해야 합니다.
힌트: 자세한 정보는 'git push --help'의 &quot;Note about fast-forwards' 부분을
힌트: 참고하십시오.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 상황에서 &lt;b&gt;rebase&lt;/b&gt;를 통해 커밋을 선택, 이어붙이는 방식으로도 해결할 수 있겠지만&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동일한 코드라인에 대한 변경사항이 없어 충돌하지 않을 것이라는 생각이들어 다른 방법을 찾아보았다.&lt;/b&gt;&lt;br /&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;span style=&quot;background-color: #f6e199;&quot;&gt;`git fetch origin`&lt;/span&gt; 이후&lt;span style=&quot;color: #343541; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; `git merge origin/main`&lt;/span&gt; 명령어를 통해 정상적으로 커밋 로그에 병합할 수 있었다.&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. git merge origin/main을 실행하면 Git은 원격 저장소(origin/main) 변경 사항을 로컬 브랜치와 결합하려고 시도한다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 변경 사항이 충돌하지 않으면 Git은 브랜치 히스토리에 따라 fast-forward merge 혹은 새로운 merge(커밋)를 수행한다.&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;공통 조상 식별: Git은 로컬 브랜치와 원격 브랜치 &lt;b&gt;모두에서 공유하는&lt;/b&gt; &lt;b&gt;가장 최근의 공통 조상 커밋&lt;/b&gt;을 찾는다 (기준)&lt;/li&gt;
&lt;li&gt;변경 사항 비교: Git은&lt;b&gt; 공통 조상 커밋 이후의 로컬 브랜치와 원격 브랜치(origin/main)의 변경 사항을 비교한다&lt;/b&gt;. &lt;b&gt;충돌이 없으면&lt;/b&gt; Git은 fast-forward 병합 또는 새로운 병합 커밋을 수행할 수 있다.&lt;/li&gt;
&lt;li&gt;Fast-forward 병합: &lt;b&gt;로컬 브랜치가 원격 브랜치보다 뒤쳐져 있고(더 오래된 커밋)&lt;/b&gt; 공통 조상 이후 &lt;b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;로컬 브랜치에 새로운 커밋이 없는 경우 Git은 fast-forward 병합을 수행&lt;/span&gt;&lt;/b&gt;할 수 있다. 이 경우 Git은 로컬 브랜치 포인터를 원격 브랜치(origin/main)의 최신 커밋으로 이동시킨다.&lt;/li&gt;
&lt;li&gt;병합 커밋: 로컬 브랜치가 공통 조상 커밋 이후&lt;b&gt; 새로운 커밋이 있는 경우&lt;/b&gt; &lt;b&gt;Git은 두 브랜치의 변경 사항을 결합한 새로운 병합 커밋을 만든다&lt;/b&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;충돌 해결: 로컬 브랜치와 원격 브랜치의 변경 사항 간에 충돌이 있는 경우 Git은 병합 프로세스를 중단하고 충돌하는 파일을 &lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;수동으로 충돌을 해결하고 변경 사항을 커밋하여 병합을 완료해야 한다. ( 나의 경우는 충돌사항이 없었다.)&lt;/span&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;참고: &lt;a href=&quot;https://www.atlassian.com/git/tutorials/using-branches/git-merge&quot;&gt;https://www.atlassian.com/git/tutorials/using-branches/git-merge&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발</category>
      <category>깃</category>
      <category>충돌</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/97</guid>
      <comments>https://devpanda.tistory.com/97#entry97comment</comments>
      <pubDate>Thu, 16 Mar 2023 23:52:02 +0900</pubDate>
    </item>
    <item>
      <title>자바 서블릿에서의 session</title>
      <link>https://devpanda.tistory.com/96</link>
      <description>&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;Session은 영구적이고 상호작용적인 정보 교환을 전제하는 둘 이상의 통신 장치나 &lt;b&gt;컴퓨터와 사용자 간의 대화나 송수신 연결상태를 의미&lt;/b&gt;하는 보안적인 다이얼로그(dialogue) 및 시간대를 가리킨다. - 위키 백과 -&lt;/i&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;HTTP 통신 구조는 &lt;a href=&quot;https://devpanda.tistory.com/92&quot;&gt;HTTP 통신의 이해&lt;/a&gt; 를 참고할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;세션 동작 과정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 같은 클라이언트-서버 프로토콜에서 세션은 세 가지 과정으로 이루어진다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트가 (TCP) &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;b&gt;데이터와 상태 코드를 돌려보낸다&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;(HTTP/1.1부터는 이 과정 이후 연결을 닫지않는다. == 2, 3번 과정이 몇 번에 걸쳐 일어난다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이를 로그인 과정에 대입한다면, (연결 수립 전제)&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;클라이언트&lt;/b&gt;는 로그인을 &lt;b&gt;요청&lt;/b&gt;한다. - 요청&lt;/li&gt;
&lt;li&gt;&lt;b&gt;WAS&lt;/b&gt;에서는 &lt;b&gt;DB&lt;/b&gt;에 사용자 정보를 확인, &lt;b&gt;검증&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;검증이 된 경우 &lt;b&gt;세션저장소&lt;/b&gt; 에서 회원정보 세션을 생성하고 세션ID(키)를 발급한다.&lt;/li&gt;
&lt;li&gt;세션ID를 쿠키에 담아 클라이언트로 전송한다. - 응답&lt;/li&gt;
&lt;li&gt;이후 클라이언트가 서버에 &lt;b&gt;재요청&lt;/b&gt;하게 될 때 &lt;b&gt;세션 ID를 헤더쿠키&lt;/b&gt;에 넣어 데이터를 요청한다.&lt;/li&gt;
&lt;li&gt;서버는 &lt;b&gt;세션ID&lt;/b&gt;를 통해 &lt;b&gt;클라이언트(회원정보)를 구별&lt;/b&gt;하여 알맞게 응답한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바 SevletContext 내에서의 세션&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;서블릿 컨테이너(아파치 톰캣)가 시작되면, 해당 서블릿 컨테이너는 모든 웹 어플리케이션들을 배포하고 로드(load)한다.&lt;/li&gt;
&lt;li&gt;웹 어플이케이션이 로드되면 서블릿 컨테이너는 &lt;b&gt;ServletContext를 한번 생성&lt;/b&gt;하여, &lt;b&gt;서버의 메모리에 보관&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;서블릿 컨테이너는 특정 포트번호(8080, 80)에서 HTTP 요청을 받는 웹 서버에 연결된다.&lt;/li&gt;
&lt;li&gt;클라이언트가 요청을 보낼때 서블릿 컨테이너는 HTTPServletRequest, HTTPServletResponse 인스턴스를 생성,&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;code&gt;chain.doFilter(request, response)&lt;/code&gt;를 호출하면 req, res가 다음 필터로 넘어가거나 서블릿에 도달&lt;/li&gt;
&lt;li&gt;서블릿의 경우 &lt;code&gt;service()&lt;/code&gt; 메서드가 호출되고 &lt;code&gt;doXXX()&lt;/code&gt; 메서드를 호출한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클라이언트가 &lt;b&gt;처음으로 웹앱에 방문&lt;/b&gt;하거나 &lt;b&gt;&lt;code&gt;request.getSession()&lt;/code&gt;을 통해 HttpSession 을 처음으로 가져오면,&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서블릿 컨테이너는 새로운 HttpSession 객체를 생성&lt;/b&gt;하고 길고 유니크한 ID 를 생성 후 서버 메모리에 저장한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는 &lt;code&gt;session.getId()&lt;/code&gt;를 통해 가져올 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서블릿 컨테이너는 JSESSIONID란 이름을 key로, 생성한 session ID를 value로 하여 HTTP 응답의 Set-Cookie header에 cookie로 설정합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;HTTP 쿠키 스펙에 따라 클라이언트(브라우저)는 쿠키가 &lt;b&gt;&lt;i&gt;유효한 동안&lt;/i&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;b&gt;&lt;i&gt;유효한 동안&lt;/i&gt;&lt;/b&gt; : 고유 식별자가 만료되지 않은 세션을 참조하고 도메인 및 경로가 올바른 경우&lt;/li&gt;
&lt;li&gt;HttpSession의 기본값은 30분이며 web.xml 의 를 통해 설정가능&lt;/li&gt;
&lt;li&gt;웹브라우저 인스턴스(탭,창)이 실행되는 동안 세션 쿠키가 활성화되고, 이를 닫으면 session 이 삭제된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서블릿 컨테이너는 들어오는 모든 HTTP 요청의 쿠키헤더에서 JSESSIONID 라는 이름의 쿠키가 있는지 확인하고,&lt;/li&gt;
&lt;li&gt;그 값(길고 유니크한 session id)을 이용해 서버 메모리에 저장된 HttpSession을 가져온다.&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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies&quot;&gt;HTTP 쿠키 - MDN&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://semtax.tistory.com/92&quot;&gt;톰캣 에서는 어떻게 JSESSIONID 를 만드는 것일까&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://fomaios.tistory.com/entry/Network-%EC%84%B8%EC%85%98Session%EC%9D%B4%EB%9E%80-What-is-a-Session#recentEntries&quot;&gt;세션(Session)이란? (What is a Session?)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jojoldu.tistory.com/118&quot;&gt;서블릿의 인스턴스화, session, 멀티스레딩에 관련된 질문과 답변에 대한 번역&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발</category>
      <category>서블릿</category>
      <category>세션</category>
      <category>자바</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/96</guid>
      <comments>https://devpanda.tistory.com/96#entry96comment</comments>
      <pubDate>Tue, 14 Mar 2023 11:38:50 +0900</pubDate>
    </item>
    <item>
      <title>서블릿이 static resouces 들을 처리하지 못하는 경우(css, js, 이미지 로딩 실패)</title>
      <link>https://devpanda.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 게시판을 스프링 프레임워크 없이 서블릿만으로만 구현하는 도중 &lt;b&gt;jsp 파일이 외부 css, js 파일들을 로딩하지 못하는 문제에 마주했다&lt;/b&gt;.&lt;/p&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;우선 브라우저는 html, jsp 페이지들을 받아와 렌더하는 과정에서 &lt;code&gt;&amp;lt;link rel='stylesheet'type=&quot;text/css&quot;&lt;/code&gt; 같은 링크 태그를 마주한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;별도의 새로운 Request를 서버에 요청&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;이 과정에서 자바 서블릿 프로젝트의 경우 &lt;b&gt;DefaultServlet이 이 정적 콘텐츠들을 처리한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제는, 개발자가 자신이 만든 servlet.java 코드 속 WebServlet 애노테이션에 루트 url을 매핑해주었을 때 생긴다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 서블릿 컨테이너와 웹 애플리케이션은 다음과 같은 url pattern 으로 연동이 가능하다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;'/' 로 시작하고 '/*' 으로 끝나는 path 매칭&lt;/li&gt;
&lt;li&gt;&quot;*.action&quot; 과 같은 확장자 매칭&lt;/li&gt;
&lt;li&gt;&lt;b&gt;'/' 만 정의한 경우 디폴트 서블릿&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;그 외 동치 매칭&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 프로젝트에서 발생한 문제가 바로 위의 3번이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우 프론트 컨트롤러 패턴으로, &lt;b&gt;디스패쳐 서블릿이 모든 리퀘스트를 받아 각 컨트롤러(커맨드) 메서드에 전달&lt;/b&gt;하는 방식을 택했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉 한 서블릿에서 모든 리퀘스트를 받게 디자인했다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;처음엔 '/*'와 같이 모든 url들을 동적으로 매칭하려고 했다.&lt;/h4&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;@WebServlet(&quot;/*&quot;)
public class FrontController extends HttpServlet {
  @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response){
    String url = request.getRequestURI();
            if (Objects.equals(url, &quot;/&quot;)) {
                request.getRequestDispatcher(&quot;/home.jsp&quot;).forward(request, response);
            }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게되면 디스패쳐 서블릿이 모든 정적 요청들을 다 받아들인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 정적 리소스들을 처리해주는 디폴트 서블릿으로 도달하지 못하고 위 프론트컨트롤러 자바클래스 내에서 처리를 시도한다.&lt;/p&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;pre class=&quot;scala&quot;&gt;&lt;code&gt;@WebServlet(&quot;/&quot;)
public class FrontController extends HttpServlet {
  @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response){
    String url = request.getRequestURI();
            if (Objects.equals(url, &quot;/&quot;)) {
                request.getRequestDispatcher(&quot;/home.jsp&quot;).forward(request, response);
            }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 매핑하면 FrontController 내에서 jsp 파일로 포워드하고 있으니 jsp 파일 자체는 서빙되지만, 거기에 포함된 js, css 파일들은 로드되지 않는다. 첫번째 경우처럼 모든 리퀘스트를 가로채서 생기는 경우는 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 왜?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드가 css, js 파일들을 로드하지 못하는 이유는 &lt;b&gt;url value가 '/' 로 정의된 경우는 상술했듯 디폴트서블릿&lt;/b&gt;인데, 이는 &lt;code&gt;org.apache.catalina.servlets&lt;/code&gt; 패키지 안에 존재하며 위치는 tomcat/lib/catalina.jar 에 묶여있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이 디폴트서블릿은 HTML, CSS, JS, IMG 같은 정적 리소스들을 처리한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 정적 리소스를 처리할 디폴트 서블릿을 개발자가 디스패쳐서블릿에 재정의함으로써 정적 파일들이 적절하게 로딩되지 않는것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 원인을 알았으니 디폴트 서블릿을 재정의 하지않게 value 혹은 urlPattern을 변경해주면 CSS 가 잘 로딩된다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;@WebServlet(urlPatterns = {&quot;/home&quot;, &quot;/login&quot;, &quot;/signup&quot;} )
public class FrontController extends HttpServlet {
  @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response){
    String url = request.getRequestURI();
            if (Objects.equals(url, &quot;/&quot;)) {
                request.getRequestDispatcher(&quot;/home.jsp&quot;).forward(request, response);
            }
}&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;1.png&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;1896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbVRpN/btrZbQYKPDB/jpSjiOJymvvwC23YTqNsQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbVRpN/btrZbQYKPDB/jpSjiOJymvvwC23YTqNsQk/img.png&quot; data-alt=&quot;tomcat/conf/web.xml 에 디폴트서블릿이 매핑되어있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbVRpN/btrZbQYKPDB/jpSjiOJymvvwC23YTqNsQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbVRpN%2FbtrZbQYKPDB%2FjpSjiOJymvvwC23YTqNsQk%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;1930&quot; height=&quot;1896&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;1896&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;tomcat/conf/web.xml 에 디폴트서블릿이 매핑되어있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개발/자바</category>
      <category>디폴트서블릿</category>
      <category>서블릿</category>
      <category>자바</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/95</guid>
      <comments>https://devpanda.tistory.com/95#entry95comment</comments>
      <pubDate>Mon, 13 Feb 2023 23:11:00 +0900</pubDate>
    </item>
    <item>
      <title>myBatis 3) 쿼리에 파라미터에 객체 전달 시 프로퍼티 찾지 못할 때</title>
      <link>https://devpanda.tistory.com/94</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&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;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;myBatis 3 매퍼 SQL 프라그먼트에 parameter 를 전달할때,&lt;/h3&gt;
&lt;ol 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;서블릿 프로젝트&lt;/span&gt;로 진행시, DAO에서 파라미터에 VO를 담아준다면?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fragment에서 받을 때 &lt;code&gt;Map.property&lt;/code&gt; 혹은 &lt;code&gt;VO.property&lt;/code&gt; 라고 명시/사용 해줘야한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AND title like CONCAT('%',#{searchCriteria.keyword},'%')&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;스프링 프레임워크&lt;/span&gt; 레포지토리에서 VO(DTO)를 파라미터로 넘겨줄 시 반대로 명시할 필요 없이 필드명만 입력해줘도 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;AND title like CONCAT('%',#{keyword},'%')&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 예시&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;0. 사전조건&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아티클 매퍼 인터페이스와 파라미터로 전달될 VO 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// ArticleMapper.java

/**
 * 게시글 매퍼 인터페이스
 */
@Mapper
public interface ArticleMapper {

    /**
     * 조건에 맞는 게시글 리턴
     * @param board 게시판 종류. String substitute(${}) 를 사용하기 때문에 서비스 내에서 정해진 값만 전달
     * @return 게시글 리스트
     */
    public List&amp;lt;ArticleVO&amp;gt; selectSearchArticles(@Param(&quot;board&quot;) String board, @Param(&quot;dbLimitOffset&quot;) Integer dbLimitOffset, @Param(&quot;searchCriteria&quot;)
            SearchCriteriaVO searchCriteria);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;// SearchCriteriaVO.class
public class SearchCriteriaVO {

  /**
         * 검색 키워드
         */
  private String keyword;

  /**
         * 게시판 ID
         */
  private Integer boardId;

  /**
         * 검색조건 시작날짜
         */
  private String startDate;

  /**
         * 검색조건 종료날짜
         */
  private String endDate;

  /**
         * 페지네이션값, 현재페이지
         */
  private Integer currentPage = 1;

  /**
         * dbLimit offset. preparedStatement 사용을 위해서는 currentPage 값으로 연산 불가능..
         */
  private Integer dbLimitOffset = 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 서블릿 프로젝트 예시&lt;/h4&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;!-- article_mapper.xml --&amp;gt;

&amp;lt;!-- 재사용을 위한 SQL 프라그먼트  --&amp;gt;
&amp;lt;sql id=&quot;searchCondition&quot;&amp;gt;
  &amp;lt;trim prefix=&quot;where (&quot; suffix=&quot;)&quot; prefixOverrides=&quot;AND&quot;&amp;gt;
    &amp;lt;if test=&quot;searchCriteria != null&quot;&amp;gt;
      AND title like CONCAT('%',#{searchCriteria.keyword},'%')
    &amp;lt;/if&amp;gt;
    &amp;lt;if test=&quot;searchCriteria != null&quot;&amp;gt;
      AND created &amp;amp;gt;= #{searchCriteria.startDate}
      OR modified &amp;amp;gt;= #{searchCriteria.startDate}
    &amp;lt;/if&amp;gt;
    &amp;lt;if test=&quot;searchCriteria != null&quot;&amp;gt;
      AND created &amp;amp;lt;= #{searchCriteria.endDate}
      OR modified &amp;amp;lt;= #{searchCriteria.endDate}
    &amp;lt;/if&amp;gt;
  &amp;lt;/trim&amp;gt;
&amp;lt;/sql&amp;gt;

&amp;lt;!-- 실제 select 쿼리문  --&amp;gt;
&amp;lt;select id=&quot;selectSearchArticles&quot; resultType=&quot;vo.ArticleVO&quot;&amp;gt;
  SELECT *
  FROM ${board}
  &amp;lt;include refid=&quot;searchCondition&quot;&amp;gt;
    &amp;lt;property name=&quot;searchCriteria&quot; value=&quot;searchCriteria&quot;/&amp;gt;
  &amp;lt;/include&amp;gt;
  ORDER BY id DESC
&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 SQL 프라그먼트 코드에서 확인할 수 있듯 &lt;code&gt;#selectSearchArticles&lt;/code&gt; select 쿼리문에 전달 된 &lt;b&gt;&lt;code&gt;searchCriteira&lt;/code&gt; 객체의 프로퍼티를 &lt;code&gt;searchCriteria.startDate&lt;/code&gt;와 같이 직접 명시해준 형태로 사용한다&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 스프링 프레임워크 사용시&lt;/h4&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;!-- article_mapper.xml --&amp;gt;

&amp;lt;!-- 재사용을 위한 SQL 프라그먼트  --&amp;gt;
&amp;lt;sql id=&quot;searchCondition&quot;&amp;gt;
  &amp;lt;trim prefix=&quot;where (&quot; suffix=&quot;)&quot; prefixOverrides=&quot;AND&quot;&amp;gt;
    &amp;lt;if test=&quot;searchCriteria != null&quot;&amp;gt;
      AND title like CONCAT('%',#{keyword},'%')
    &amp;lt;/if&amp;gt;
    &amp;lt;if test=&quot;searchCriteria != null&quot;&amp;gt;
      AND created &amp;amp;gt;= #{startDate}
      OR modified &amp;amp;gt;= #{startDate}
    &amp;lt;/if&amp;gt;
    &amp;lt;if test=&quot;searchCriteria != null&quot;&amp;gt;
      AND created &amp;amp;lt;= #{endDate}
      OR modified &amp;amp;lt;= #{endDate}
    &amp;lt;/if&amp;gt;
  &amp;lt;/trim&amp;gt;
&amp;lt;/sql&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파라미터로 전달 된 객체(map, VO) 속 프로퍼티와 SQL 쿼리 파라미터명을 알아서 매핑해주어 &lt;b&gt;객체.프로퍼티 형태가 아닌 &lt;code&gt;#{프로퍼티}&lt;/code&gt; 명으로만 사용해줘도된다!&lt;/b&gt;&lt;/p&gt;</description>
      <category>개발/자바</category>
      <category>마이바티스</category>
      <category>자바</category>
      <category>파라미터</category>
      <category>프로퍼티</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/94</guid>
      <comments>https://devpanda.tistory.com/94#entry94comment</comments>
      <pubDate>Fri, 10 Feb 2023 18:19:41 +0900</pubDate>
    </item>
    <item>
      <title>myBatis 3 쿼리문에 parameter 문법 (${}, #{})</title>
      <link>https://devpanda.tistory.com/93</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;마이바티스를 이용하면 SQL문에 파라미터를 쓸 수 있다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;myBatis 공식문서에 Parameters 섹션에 기술된 #{} 과 String substitution의 ${} 이 그것들이다. 예를들어,&lt;/p&gt;
&lt;pre class=&quot;vbnet&quot;&gt;&lt;code&gt;  &amp;lt;select id=&quot;search&quot; resultType=&quot;ArticleVO&quot;&amp;gt;
    SELECT *
    FROM   article
    WHERE  article_id = #{articleId}
  &amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 사용하거나 &lt;code&gt;WHERE  article_id = '${articleId}'&lt;/code&gt; 와 같이 사용하면 파라미터를 전달해줄 수 있다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Mapper
public interface ArticleMapper {

    public List&amp;lt;ArticleVO&amp;gt; selectSearchArticles(@Param(&quot;articleId&quot;) String articleId);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 매퍼인터페이스의 &lt;code&gt;selectSearchArticles&lt;/code&gt; 메서드를 통해 스트링 형태의 파라미터를 전달하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 #{}, ${} 의 차이는 무엇일까?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#{} 을 사용하게 되면 PreparedStatement를 생성한다.&lt;/h3&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT *
FROM   article
WHERE  article_id = ?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 물음표에 파라미터가 바인딩되어 수행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이렇게 파싱된 쿼리문은 캐싱되어 효율적이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 따옴표가 붙어 파싱되기에 SQL 인젝션으로부터 ${}에 비해 안전하다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;${}을 사용하면 값이 입력된 상태로 쿼리문이 수행된다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 파라미터가 변경될때마다 항상 쿼리문 파싱이 진행되며 성능상 불리하며, 작은 따옴표가 붙지 않기 때문에 스트링을 쿼리로 인식할 수 있어 &lt;b&gt;SQL 인젝션에 취약하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그러나 요녀석은 sql문의 메타데이터, 즉 테이블, 컬럼명에 쓸 수 있다는 장점(?)이 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 결국 테이블, 컬럼명에 쓰는것도 아래와 같은 SQL 인젝션의 위험이 있지 않을까한다.&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT * FROM ${tableParam}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT * FROM user_data; DROP TABLE users;&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;보안과 성능상 차이는 알고있었지만 SQL 파라미터(#{})가 테이블명에 사용되지 않아 새롭게 찾아본 내용인데, 안전한 쿼리문을 위해서는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 테이블명을 분리해 매퍼를 만들어주던지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 클라이언트가 테이블명을 임의로 줄 수 없도록 만들어야할 것 같다.&lt;/p&gt;</description>
      <category>개발/자바</category>
      <category>SQL</category>
      <category>마이바티스</category>
      <category>자바</category>
      <category>파라미터</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/93</guid>
      <comments>https://devpanda.tistory.com/93#entry93comment</comments>
      <pubDate>Thu, 9 Feb 2023 18:01:40 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 통신의 이해</title>
      <link>https://devpanda.tistory.com/92</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;HTTP 통신의 구조&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;HTTP(Hyper Text Transport Protocol, 하이퍼텍스트 전송 프로토콜)는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;브라우저-서버가 통신&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;할 수 있게 만들어주는 프로토콜(규약)이다. 주로 HTML 문서를 주고받는데 쓰인다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;일반적으로 전송 계층 프로토콜로 TCP, 네트워크 계층 프로토콜로 IP를 사용한다. TCP/IP 에서 IP 주소를 사용해 통신할 컴퓨터를 결정하고, 포트 번호를 사용해 해당 컴퓨터의 어떤 프로그램과 통신할지 결정한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;HTTP에서는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;클라이언트가 서버에 요청 메세지를 보내고, 서버는 클라이언트 요청(Request)에 대한 응답(Response을 반환&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;한다. 연결 상태를 유지하지 않는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;비연결성(stateless) 프로토콜&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Http Request는 클라이언트가 서버로 전달해 서버의 액션이 일어나게끔하는 메세지다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Request 구조는&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;start Line,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Header Lines,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Body 로 이루어져있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;시작라인&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;은 요청이 시작되는 줄로 &lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;HTTP메서드(GET, POST 등)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;요청 타겟, 즉 URL, 포트, 도메인&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;HTTP 버전이 들어간다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;헤더라인은..&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;대소문자 구분 없는 문자열 다음 콜론(' : ')이 붙으며, 그 뒤 값은 헤더에 따라 달라진다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;헤더는 또다시 General, Request, Entity 헤더로 나눌수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;바디는..&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;리퀘스트 마지막 부분에 들어가며, 리소스를 가지고 오는 요청(GET, DELETE ...)에는 들어가지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;바디는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;단일자원 / 다중 리소스 본문&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 나누어진다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;GET / HTTP/1.1 -&amp;gt; 리퀘스트 라인
// 리퀘스트헤더 시작
Host: www.naver.com:443 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-ch-ua: &quot;Chromium&quot;;v=&quot;92&quot;, &quot; Not A;Brand&quot;;v=&quot;99&quot;, &quot;Google Chrome&quot;;v=&quot;92&quot;
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
// 리퀘스트헤더 종료
---공백 라인---
바디&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Accept, Content-Type?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;요청 헤더에는 Accept, content-type이 있다. &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Accept&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 헤더는 서버가 응답하기 위해 HTTP 메시지를 구성할때, &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;알맞은 형태로 제공해달라는 정보&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이고, &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Content-Type&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 헤더는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;HTTP 메시지에 포함된 데이터가 어떤 형태로 구성되는지 서버에게 알려준다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉, 클라이언트에서 HTTP &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;요청을 할때 HTTP 메세지에 포함되는 형태에 따라 콘텐트타입 헤더를 제공&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;해야하고, 서버로부터 특정 메세지 형태로 제공받고 싶다면 Accept 헤더에 알맞은 값을 지정해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Accept 헤더에 주로 사용되는 헤더값&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;text/plain&lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;, text/html&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, text/css, text/javascript&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;application/json&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, application/xml, &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;application/octet-stream&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Content-Type&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;요청 데이터가 폼 데이터형태 일때 -&amp;gt; &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;대용량 바이너리 데이터를 전송(파일첨부)할때 -&amp;gt; &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;multipart/form-data&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Content-Type: Application/octet-stream - 디폴트 미디어 타입은 운영체제 종종 실행파일, 다운로드를 의미&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;JSON 형태일때 -&amp;gt; &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;application/json&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;HTTP Response는 요청에 대한 서버의 응답이다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Response는 &lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Status Line&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Header&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Body 로 구성된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Status Line에는..&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;프로토콜 버전&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;요청의 성공여부 - HTTP 상태코드(404, 200...)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;짧은 상태 텍스트 (Not Found) 가 담겨있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Header에는&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;마찬가지로 HTTP 헤더 기본 구조를 따른다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;General Header, Request Header, Entity Header으로 나눌 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Body&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;201, 204 와 같은 상태 코드를 가진 응답에는 보통 본문이 없다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;본문은 크게 세 종류로 나뉜다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;길이가 알려진&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 단일 파일로 구성된 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;단일-리소스 본문&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 헤더 두개(Content-Type, Content-Lenght) 로 정의한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;길이를 모르는&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 단일 파일로 구성된 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;단일-리소스 본문&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: Transfer-Encoding이 Chuncked 로 설정되어 있으며 파일은 청크로 나뉘어 인코딩 되어있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;서로 다른 정보&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 담고 있는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;multipart로&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 이루어진 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;다중 리소스 본문&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;HTTP/1.1 200 // Status Line
// Response header 시작
cache-control: no-cache, no-store, must-revalidate
content-encoding: gzip
content-type: text/html; charset=UTF-8
date: Wed, 25 Aug 2021 02:42:02 GMT
p3p: CP=&quot;CAO DSP CURa ADMa TAIa PSAa OUR LAW STP PHY ONL UNI PUR FIN COM NAV INT DEM STA PRE&quot;
pragma: no-cache
referrer-policy: unsafe-url
server: NWS
strict-transport-security: max-age=63072000; includeSubdomains
x-frame-options: DENY
x-xss-protection: 1; mode=block
// Response header 시작
-- 공백 라인--
바디&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/네트워크</category>
      <category>http</category>
      <category>멀티파트</category>
      <category>콘텐트타입</category>
      <category>통신</category>
      <category>프로토콜</category>
      <category>헤더</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/92</guid>
      <comments>https://devpanda.tistory.com/92#entry92comment</comments>
      <pubDate>Fri, 6 Jan 2023 00:05:03 +0900</pubDate>
    </item>
    <item>
      <title>자바의 데이터 타입과 메모리 영역</title>
      <link>https://devpanda.tistory.com/91</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;자바 원시타입, 참조타입(Primitive type, Reference type)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;데이터 타입&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이란, 해당 데이터가 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;어떻게 메모리에 저장&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;되고 프로그램에서 어떻게 처리되어야 하는지 명시적으로 알려주는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자바에서는 크게 기본형타입과 참조형 타입이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;원시 타입(Primitive Type)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;논리형 boolean, 정수형 byte, int, short, long, 실수형 float, double, 문자형 char 이 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;8가지 기본형 타입을 미리 정의하여 제공한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기본값이 있기 때문에 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Null이 존재하지 않는다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 기본형 타입에 Null을 넣고싶다면 래퍼 클래스를 활용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;실제 값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 저장하는 공간으로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;스택 메모리에&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 저장된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;담을수있는 크기를 벗어나면 컴파일 에러가 발생한다.&lt;/span&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;&lt;span&gt;참조 타입(Reference Type)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;배열 Array, 열거 Enumeration, 클래스 Class, 인터페이스 Interface&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;가 이에 해당한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기본형 타입을 제외한 타입들은 모두 참조형 타입이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;값이 저장되어있는 곳의 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;주소값을 저장&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하는 공간으로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;힙 메모리&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 저장된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;컴파일 시점에 에러가 없지만, 객체나 배열을 Null 값으로 받았을 경우 NullPointException이 발생한다.&lt;/span&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;스택(Stack)/힙(Heap) 영역&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;정적 메모리 스택(Stack) 영역&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;힙 영역에 생성된 객체(Object) 타입의 데이터 참조값이 할당된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;원시타입의 데이터가 값과 함께 할당된다.- 참조값이 아닌 실제 값을 스택에 저장한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;각 쓰레드는 자신만의 스택을 가진다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;객체 안 메서드 작업이 종료되면 할당된 메모리 공간은 반환되어 비어진다. &lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;함수가 종료된 경우 내부에 선언된 지역변수들은 Stack에서 pop 되어 사라진다.&lt;/span&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;&lt;span&gt;동적 메모리 힙(Heap) 영역&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;주로 긴 생명주기를 가지는 데이터들이 저장된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;스택에 있는 데이터를 제외한 부분이라 보면 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;모든 Object 타입(Integer, Sring, ArrayList...) 등이 힙에 생성된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;쓰레드 개수와 상관없이 힙 영역은 단 하남나 존재한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;힙 영역에 있는 오브젝트들을 가리키는 레퍼런스 변수가 스택에 올라간다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// 힙 메모리 예시를 위한 코드
public&amp;nbsp;class&amp;nbsp;Main&amp;nbsp;{
&amp;nbsp; &amp;nbsp;public&amp;nbsp;static&amp;nbsp;void&amp;nbsp;main(String[]&amp;nbsp;args) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;int&amp;nbsp;port&amp;nbsp;=&amp;nbsp;4000;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;String&amp;nbsp;host&amp;nbsp;=&amp;nbsp;&quot;localhost&quot;;
&amp;nbsp; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;&lt;span&gt;위 클래스에서 &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt; 는 원시타입(int)에 해당하기에 &lt;/span&gt;&lt;span&gt;port = 4000&lt;/span&gt;&lt;span&gt; 이 스택 영역에 등록된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2.&amp;nbsp;&lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;는 참조타입(String)으로 &lt;/span&gt;&lt;span&gt;String 'localhost'&lt;/span&gt;&lt;span&gt;는 힙 영역에 등록되고&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;String 은 Objec를 상속받아 구현된다. Object 타입은 최상위 부모클래스고, 다형성에 의해 Object 타입으로 레퍼런스가 가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3. 스택에서 &lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;라는 이름으로 생성된 변수가 힙 영역의 &lt;/span&gt;&lt;span&gt;String 'localhost'&lt;/span&gt;&lt;span&gt;를 레퍼런스한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/자바</category>
      <category>데이터타입</category>
      <category>메모리</category>
      <category>자바</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/91</guid>
      <comments>https://devpanda.tistory.com/91#entry91comment</comments>
      <pubDate>Tue, 3 Jan 2023 11:30:24 +0900</pubDate>
    </item>
    <item>
      <title>자바 - checked Exception, unchecked Exception</title>
      <link>https://devpanda.tistory.com/90</link>
      <description>&lt;h4&gt;Exception?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Java object 의 Throwable 클래스에는 Error / Exception 클래스 존재한다.&lt;/li&gt;
&lt;li&gt;Exception은 java.lang.Exception 클래스와 그 서브클래스들이 쓰이는 상황이다.&lt;/li&gt;
&lt;li&gt;이 예외들은 &lt;strong&gt;Checked Exception&lt;/strong&gt; 과 &lt;strong&gt;Unchecked Exception&lt;/strong&gt; 두 가지로 나눌 수 있다.&lt;/li&gt;
&lt;li&gt;언체크 예외(unchecked exception)은  RuntimeException을 상속한 것&lt;/li&gt;
&lt;li&gt;체크 예외는 그 이외의 예외들을 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br&gt; &lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Checked Exception &lt;strong&gt;체크 예외&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;체크 예외는 상술했듯 &lt;strong&gt;RuntimeException을 상속하지 않는 예외&lt;/strong&gt;들이다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;컴파일 단계&lt;/strong&gt;에서 확인된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;복구가 가능&lt;/strong&gt;한 예외들이기에 반드시 catch, throws를 통해 &lt;strong&gt;예외를 처리하는 코드를 함께 작성&lt;/strong&gt;해야한다.&lt;/li&gt;
&lt;li&gt;ClassNotFoundException, IOException, SQLException 등이 해당한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;​    &lt;/p&gt;
&lt;br&gt;

&lt;h4&gt;Unchecked Exception &lt;strong&gt;언체크 예외&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;런타임 예외&lt;/strong&gt;라고도 부르는 언체크 예외들은 &lt;strong&gt;명시적인 예외 처리를 강제하지 않는다&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;따라서 unchecked exception인 것이다. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;실행 단계&lt;/strong&gt;에서 확인된다.&lt;/li&gt;
&lt;li&gt;이들은 프로그램에 오류가 있을때 발생하도록 의도된 것들이다.&lt;/li&gt;
&lt;li&gt;NullPointerException, illegalArgumentException, ArrayIndexOutOfBoundsException 등이 해당한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;  &lt;/p&gt;
&lt;h4&gt;일반적인 예외 처리 방법들&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;예외복구&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;예외 복구의 핵심&lt;/strong&gt;은 &lt;strong&gt;예외가 발생&lt;/strong&gt;하여도 &lt;strong&gt;Application은 정상적으로 동작&lt;/strong&gt;한다는 것.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;private void mayThrowExceptionLogic() {
    int maxTry = 20;
    while(maxTry --&amp;gt; 0) {
        try {
            // ???Exception 이 Throw 될 수 가능성이 있는 로직
        // 성공 시 return, 해당 메소드 종료
        return ;
        } catch(???Exception e) {
            // Error 로그 출력
        // 실패 로직 존재 시 원상 복구
        // 일정 시간 동안 대기
        } finally {
            // 작업에 사용한 Resource 반환 및 정리
        }
    }
    // 최대 횟수 실패시 예외 Throw
    throw new MaxTryFailedException();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;예외 회피&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;자신이 예외를 처리하지 않고 호출한 쪽으로 throw 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;무분별하게 사용해선 안된다. 호출한 쪽에서 예외를 처리하는게 맞을 경우에만 사용한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;private void mayThrowExceptionLogic() throws ???Exception {
    // 비즈니스 로직
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;예외전환&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;예외를 복구해 정상적 상태로 만들수없기 때문에 예외가 발생한 메소드 밖으로 던지는 방법이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;적절한 예외로 전환해서 던진다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;try {
    // Exception 발생 가능 로직
}
catch(???Exception e) {
    // Exception 로깅
        // 복구 로직
        throw CustomSpecificExceptionJustLikeNotAllowedUserException(&amp;quot;이런상황~&amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;/*
1번은 예외를 던지는 경우, 예외의 이름을 보고 어떤 문제가 있는 예외인지 알 수 있게 해준다. 
예를 들어, 사용자의 아이디가 겹치는 예외의 경우 일반적인 SQLException이 아니라, 
DuplicatedUserIDException으로 던지게 되면, 호출한 쪽에서는 단순히 SQLException이 아닌, 사용자의 아이디가 겹쳐서 발생하게된 예외인지를 인식할 수 있게 된다.
*/

/*
2번은 복구 가능한 예외가 아닌경우, RuntimeException으로 포장해서 던지는 방법이다.
이렇게 체크 예외를 언체크 예외인 RuntimeException으로 포장해서 던지는 경우, 
불필요한 throws 구문이 줄게 된다.
*/&lt;/code&gt;&lt;/pre&gt;
 &lt;br&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;중요한건?&lt;/h3&gt;
&lt;h4&gt;편한 길을 선택하지말고 어떤 방법으로 예외처리를 할지 고민하고 방법을 선택해야한다.&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Catch에 e.printStackTrace / throw 를 남발하지 말고,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;로깅, 복구 로직 등을 추가한다.&lt;/strong&gt;&lt;/p&gt;
&lt;br&gt;

&lt;br&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Error?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;에러는 시스템에 비정상적 상황이 발생했을 경우 발생한다.&lt;/li&gt;
&lt;li&gt;메무리 부족이나 스택오버플로우처럼 복구할 수 없다.&lt;/li&gt;
&lt;li&gt;이러한 에러는 개발자가 예측하기 쉽지않고, 처리할 수 있지도 않다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발</category>
      <category>언체크드</category>
      <category>예외</category>
      <category>자바</category>
      <category>처리</category>
      <category>체크드</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/90</guid>
      <comments>https://devpanda.tistory.com/90#entry90comment</comments>
      <pubDate>Thu, 22 Dec 2022 11:26:00 +0900</pubDate>
    </item>
    <item>
      <title>[디자인패턴] 빌더 패턴</title>
      <link>https://devpanda.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1주차 과제로 JSP와 바닐라 자바만으로 게시판을 구현했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 과정에서 아래와 같이 VO, DAO를 하드코딩으로 작성했고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Setter조차 사용하지 않고 무식하게 Post 객체를 생성하는 것에 지적을 받았다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;// PostVO.java
​
@Getter
@Setter
@AllArgsConstructor
public class Post {
    @NonNull
 &amp;nbsp; &amp;nbsp;private Integer post_id;
   &amp;nbsp;@NonNull
 &amp;nbsp; &amp;nbsp;private String title;
 &amp;nbsp; &amp;nbsp;@NonNull
 &amp;nbsp; &amp;nbsp;private String writer;
 &amp;nbsp; &amp;nbsp;@NonNull
 &amp;nbsp; &amp;nbsp;private String password;
 &amp;nbsp; &amp;nbsp;@NonNull
 &amp;nbsp; &amp;nbsp;private String content;
 &amp;nbsp; &amp;nbsp;@NonNull
 &amp;nbsp; &amp;nbsp;private Integer category_id;
 &amp;nbsp;
 &amp;nbsp; &amp;nbsp;private Integer view;
 &amp;nbsp; &amp;nbsp;private Date created_at;
 &amp;nbsp; &amp;nbsp;private Date modified_at;
​
}
​&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// PostDAO.java
po = new Post(
 &amp;nbsp;rs.getInt(1),
 &amp;nbsp;rs.getString(2),
 &amp;nbsp;rs.getString(3),
 &amp;nbsp;rs.getString(4),
 &amp;nbsp;rs.getInt(5),
 &amp;nbsp;rs.getString(6),
 &amp;nbsp;rs.getDate(7),
 &amp;nbsp;rs.getDate(8),
 &amp;nbsp;rs.getInt(9)
);&lt;/code&gt;&lt;/pre&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;span&gt;위와 같이 작성할 경우&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;코드 가독성이 떨어진다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;생성자 정의가 변경돼 새로운 인자가 추가될 경우, 모든 호출 코드를 변경해주어야 한다!&lt;/span&gt;&lt;/b&gt;&lt;/span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;따라서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;롬복의 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;builder&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 활용해 다시 리팩토링해보라 하셨다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Project Lombok은 @Builder를 다음과 같에 소개하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@Builder 주석은 클래스에 대한 복잡한 작성기 API를 생성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@Builder를 사용하면 클래스를 다음과 같은 코드로 인스턴스화하는 데 필요한 코드를 자동으로 생성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉 @Builder 을 통해 빌더 패턴을 위한 보일러플레이트 코드를 일일이 작성하지 않아도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;그렇다면 빌더 패턴은 무엇인가?&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;빌더 패턴(Builder pattern)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. (출처: 위키백과)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;생성자에 인자가 많을 때&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 빌더 패턴을 고려하라고 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;빌터패턴을 활용하면 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;어떤 인자를 넣어줬는지 명확히 알 수 있고,&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;불필요한 필드(null)은 굳이 선언할 필요가 없다고 한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;// 빌더 패턴을 활용한 PostVO.java (롬복 없이 보일러플레이트 코드로)
public static class Post {
 &amp;nbsp; &amp;nbsp;private final Integer postId;
 &amp;nbsp; &amp;nbsp;private final String title;
 &amp;nbsp; &amp;nbsp;private final String writer;
 &amp;nbsp; &amp;nbsp;private final String password;
 &amp;nbsp; &amp;nbsp;private final String content;
 &amp;nbsp; &amp;nbsp;private final Integer view;
 &amp;nbsp; &amp;nbsp;private final Date created_at;
 &amp;nbsp; &amp;nbsp;private final Date modified_at;
 &amp;nbsp; &amp;nbsp;private final Integer category_id;
 &amp;nbsp;
    public static class Post(Builder builder){
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.postId = builder.postId;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.title = builder.title;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.writer = builder.writer;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.password = builder.password;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.content = builder.content;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.view = builder.view;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.created_at = builder.created_at;
      this.modified_at = builder.modified_at;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;this.category_id = builder.category_id;
 &amp;nbsp;  }
 &amp;nbsp;
    
    private static class Builder {
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private final Integer postId;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private final String title;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private final String writer;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private final String password;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private final String content;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private final Integer category_id;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private Integer view;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private Date created_at;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;private Date modified_at;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;public Builder(Integer postId, String title, String writer, String password, String                         content, Integer category_id){
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (postId == null || title == null || writer == null || password == null || content ==             null || category_id == null) {
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;throw new IllegalArgumentException(&quot;... can not be null&quot;);
 &amp;nbsp; &amp;nbsp; &amp;nbsp;  }
        this.postId= postId;
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;this.title = title;
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// ...
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// 중략
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// ...
 &amp;nbsp; &amp;nbsp;    public Builder withView(Integer view){
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;this.view = view;
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return this;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;  }
 &amp;nbsp; &amp;nbsp;    public Builder withCreatedAt(Integer view){
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;this.CreatedAt = CreatedAt;
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return this;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;  }
 &amp;nbsp; &amp;nbsp;    public Builder withModifiedAt(Integer view){
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;this.ModifiedAt = ModifiedAt;
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return this;
 &amp;nbsp; &amp;nbsp; &amp;nbsp;  }
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
 &amp;nbsp;  }
 &amp;nbsp; &amp;nbsp; &amp;nbsp;
// 보일러플레이트 코드로 단순반복하기보다 롬복 @Builder 어노테이션을 사용하면 편리하다.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 위 코드를 DAO에서 활용할 때
Post post = Post.builder()
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .title(rs.getString(2))
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .writer( rs.getString(3))
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .password(rs.getString(4))
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .content(rs.getString(6))
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .created_at(rs.getDate(6))
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .category_id(rs.getInt(9))
 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  .build();
​
// 각 필드에 들어가는 인자들도 변수에 담으면 더 잘 보이겠지만..
// 어떤 필드에 어떤 값이 들어가는지 이전보다 명확하게 확인할 수 있다!&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발/객체지향개발</category>
      <category>디자인패턴</category>
      <category>빌더패턴</category>
      <category>생성패턴</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/89</guid>
      <comments>https://devpanda.tistory.com/89#entry89comment</comments>
      <pubDate>Tue, 20 Dec 2022 12:50:01 +0900</pubDate>
    </item>
    <item>
      <title>자바 클래스패스(classpath)란?</title>
      <link>https://devpanda.tistory.com/87</link>
      <description>&lt;h2&gt;자바 클래스패스(classpath)란?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;자바 언어로 작성된 클래스 파일은 자바가상머신(JVM)에서 실행된다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JVM이 모든 폴더를 찾아보는 것은 비효율적이기에, 클래스파일을 찾을 수 있게 위치의 리스트들을 제공한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JVM이 프로그램을 실행하기 위해 클래스파일을 찾는데 기준이 되는 경로가 클래스패스다&lt;/strong&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;java 확장자로 끝나는 자바 소스코드를 컴파일한다.&lt;/li&gt;
&lt;li&gt;컴파일된 소스코드는 바이너리 형태의 .class 파일로 변환된다.&lt;/li&gt;
&lt;li&gt;java runtime(jre)으로 .class 파일에 포함된 명령을 &lt;strong&gt;실행하려면, 먼저 이 파일을 찾을 수 있어야한다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;이 때 클래스패스가 사용된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;클래스패스를 지정하려면,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;환경변수 CLASSPATH를 사용하거나&lt;/li&gt;
&lt;li&gt;java runtime(jre)에 -classpath 플래그를 사용한다. &lt;strong&gt;&lt;em&gt;java -classpath &amp;quot;.;item&amp;quot; Main.java&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;클래스패스에는 다음이 포함된다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jar(Java Archive) files : 여러 자바 클래스 파일과 리소스 등 메타데이터를 하나의 파일로 모아 배포하기 위한 패키지 파일&lt;/li&gt;
&lt;li&gt;패키지 최상단 경로&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/자바</category>
      <category>자바</category>
      <category>클래스패스</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/87</guid>
      <comments>https://devpanda.tistory.com/87#entry87comment</comments>
      <pubDate>Mon, 19 Dec 2022 15:39:25 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 알고리즘 인터뷰 23장 다이나믹 프로그래밍(DP)</title>
      <link>https://devpanda.tistory.com/86</link>
      <description>&lt;h3&gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;최적 부분 구조&lt;/strong&gt; - 문제의 최적 해결방법이 부분 문제에 대한 최적 해결 방법으로 구성되는 경우의 문제&lt;/li&gt;
&lt;li&gt;DP 알고리즘을 이용하면 최적 부분 구조를 갖고있는 문제를 풀이할 수 있다.&lt;/li&gt;
&lt;li&gt;최적 부분 구조를 푸는 또 다른 알고리즘으로는 그리디 알고리즘이 있다. 그리디는 &lt;strong&gt;그 순간에 최적이라 생각하는 것을 선택&lt;/strong&gt;하며 풀이&lt;/li&gt;
&lt;li&gt;DP는 &lt;strong&gt;중복&lt;/strong&gt;된 하위 문제들의 결과를 저장해뒀다가 풀이해 나간다.&lt;/li&gt;
&lt;li&gt;중복되지 않은 문제들은 DP로 풀지 않고 병합정렬, 퀵 정렬 등을 이용해 분할정복으로 풀어나간다.&lt;/li&gt;
&lt;li&gt;다익스트라 알고리즘은 최적 부분 구조, 중복된 하위 문제들, 탐욕 선택 속성을 모두 갖는 알고리즘이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;


&lt;h3&gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;2020 11. 12. FRI  &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파이썬 알고리즘 인터뷰 - 23장 다이나믹 프로그래밍  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DP의 방법론&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;메모이제이션, 하향식 접근 : 하위 문제에 대한 정답을 계산했는지 확인해가며 자연스럽게 &lt;strong&gt;재귀&lt;/strong&gt;로 풀어나간다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;타뷸레이션, 상향식 접근 : &lt;strong&gt;하위 문제부터 풀어나가며&lt;/strong&gt; 큰 문제의 정답을 만든다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;두 방식을 피보나치 수열의 예제 코드로 비교하면 다음과 같다&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 상향식
def fib(n):
    dp[0] = 0
    dp[1] = 1
    for i in range(2, n+1):
        dp[i] = dp[i-1] + dp[i-2]
        return dp[n]
# 하향식
def fib(n):
    if n&amp;lt;=1:
        return n
    if dp[n]:
        return dp[n]
    dp[n] = fib(n-1) + fib(n-2)
    return dp[n]
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DP 대표문제 2) 배낭문제의 파이썬 풀이&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# pack 이라는 리스트 변수애 6 x 16 행렬 형태의 중간 결과 테이블이 생성된다.
cargo = [
    # 가격, 무게
    (4, 12),
    (2, 1),
    (10, 4),
    (1, 1),
    (2, 2),
]

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;def zero_one_knapsack(cargo):
    # 배낭의 총 용량
    capacity = 15
    pack = []
    for i in range(len(cargo)+1):
        pack.append([])
    for c in range(capacity+1):
        if i == 0 or c == 0:
            pack[i].append(0)
        elif cargo[i-1][1] &amp;lt;= c:
            pack[i].append(
                max(
                    cargo[i-1][0] + pack[i-1][c-cargo[i-1][1]],
                    pack[[i-1][c]]
                ))
        else:
            pack[i].append(pack[i-1][c])

        return pack[-1][-1]
```

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;원래 해시 테이블은 입력 순서가 유지되지 않는다. 파이썬 3.6 이하 버전에서는 딕셔너리 입력 순서가 유지되지 않는다. collections.OrderedDict 자료형을 이용해 이를 해결하자.  &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;



&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DP는 유난히 문제를 못풀었을때의 허탈함이 큰 것 같다. 문제 해결의 실마리(점화식)의 중요성이 유독 크게 느껴진다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;그래도 PS 대회가 아니고서야 유형이 정해져있다는 사실이 위로가 된다.  &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/북TIL</category>
      <category>다이나믹프로그래밍</category>
      <category>메모이제이션</category>
      <category>타뷸레이션</category>
      <category>파이썬알고리즘인터뷰</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/86</guid>
      <comments>https://devpanda.tistory.com/86#entry86comment</comments>
      <pubDate>Fri, 11 Nov 2022 18:21:47 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 알고리즘 인터뷰 9, 10, 11장 - 스택, 큐, 데크, 우선순위 큐,  해시 테이블</title>
      <link>https://devpanda.tistory.com/85</link>
      <description>&lt;h2&gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;스택은 거의 모든 APP을 만들때 사용&lt;/strong&gt;되는 자료구조로서, 스택과 연관된 알고리즘을 제대로 이해하느냐 못 하느냐에 따라서 기본 알고리즘을 설계할 수 있느냐 없느냐가 결정되기도 한다.&lt;/li&gt;
&lt;li&gt;FIFO로 처리되는 &lt;strong&gt;큐는 BFS, 캐시 등을 구현&lt;/strong&gt;할 때 널리 사용된다. 데크나 우선순위 큐 같은 변형들도 유용하다.  &lt;strong&gt;성능&lt;/strong&gt;을 위해 파이썬에서는 데크를 사용하는 것이 가장 좋다.&lt;/li&gt;
&lt;li&gt;파이썬에서는 대부분의 우선순위 큐 풀이에 heaqpq 모듈을 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;d2022 10. 24. ~ 2022. 11.07&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;파이썬 알고리즘 인터뷰 9장 스택, 큐, 10장 데크, 우선순위 큐, 11장 해시 테이블&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;파이썬의 Global Interpreter Lock&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt; -  **하나의 스레드가 자원을 독점하는 형태로 실행**된다.


 -  번거로운 동시성 관리를 편하게 하기 위해, 스레드 세이프 하지 않은 CPython의 메모리 관리를 쉽게하기 위해


 -  GIL로 파이썬 객체에 대한 접근을 제한하는 형태로 설계했다.


 -  *스레드 세이프 - 멀티 스레드에도 안전한 프로그래밍 개념. 스레드 세이프 하지 않은 경우 1번 스레드 값이 2번 스레드에서 변경이 될 수 있어 문제가 발생한다.*


 -  CPython이 개발되던 1994년에는 CPU가 싱글코어로 GIL을 선택할 만했고, 디자인에 아무런 문제가 없었다. 하지만 지금처럼 멀티코어가 당연한 세상에서 이런 제약은 치명적이다. **파이썬이 왜 느린가?** 를 얘기할때 가장 자주 듣게 되는 요인!&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;해시테이블&lt;/strong&gt; 또는 해시 맵은 &lt;strong&gt;키를 값에 매핑&lt;/strong&gt;할 수 있는 구조인, 연관 배열 추상자료형을 구현하는 자료구조다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;해시테이블의 가장 큰 특징은 대부분의 연산이 분할 상환 분석에 따른 시간복잡도가 O(1)이라는 점이다. -&amp;gt; &lt;strong&gt;데이터 양과 무관하게 빠른 성능&lt;/strong&gt; &lt;strong&gt;보장&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;충돌&lt;/strong&gt;은 생각보다 쉽게 일어난다. 비둘기집 원리에 따라 생일이 같으려면 366명 이상이 모여야 할 것 같다. 그러나 실제로는 23명만 모여도 50%를 넘고, &lt;strong&gt;57명이 모이면 99%를 넘어간다!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 위의 생일 중복자 실험 코드
import random

TRAIALS = 100000
smae_birthdays = 0
# 10만 번 실험 진행
for _ in range(TRAIALS):
      birthdays= []
    # 23명이 모였을 때 생일이 같을 경우 same_birthdays +=1
    for _ in range(23):
          birthday = random.randint(1, 365)
        if birthday in birthdays:
              same_birthdays +=1
            break
        birthdays.append(biorthday)
print(f&amp;quot;{same_birthdays / TRIALS * 100}&amp;quot;) 
# 50.708%&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;비둘기집 원리란 n개의 아이템을 m개의 컨테이너에 넣을 때, n&amp;gt;m 이라면 적어도 하나의 컨테이너에는 반드시 2개 이상의 아이템이 들어있다는 원리&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;아무리 좋은 해시함수라도 &lt;strong&gt;충돌은 일어난다.&lt;/strong&gt; 충돌이 발생할 경우&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;개별 체이닝&lt;/strong&gt;으로 처리한다. 충돌 발생 시 연결 리스트로 연결하는 방식을 개별 체이닝이라고 한다. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;오픈 어드레싱 방식&lt;/strong&gt;으로 해결한다. 이는 충돌 발생 시 탐사를 통해 빈 공간을 찾아나서는 방식이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;로드팩터란&lt;/strong&gt; 해시테이블에 저장된 데이터 개수 n을 버킷의 개수 k로 나눈 것이다. 이 로드팩터 비율에 따라 &lt;strong&gt;해시 함수를 재작성&lt;/strong&gt;할지, &lt;strong&gt;해시 테이블의 크기를 조정&lt;/strong&gt;해야할지를 결정한다&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;리트코드 771번 보석과 돌의 한줄 풀이&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# J = &amp;quot;aA&amp;quot;,  S = &amp;quot;aAAbbbb&amp;quot;
def numJewelsINStones(self, J:str, S:str) -&amp;gt; int:
    return sum(s in J for s in S) 
  # == return sum([True, True, True, False, False, False, False])
  # == return 3&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬의 &lt;strong&gt;zip() 함수&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;zip()함수는 2개 이상 시퀀스를 짧은 길이 기준으로 일대응 대응하는 새로운 튜플 시퀀스를 만든다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;a = [1,2,3,4,5]
b = [2,3,4,5]
c = [3,4,5]
zip(a,b) # &amp;lt;zip object at 0x105b6d0b0&amp;gt; (제너레이터)
list(zip(a,b)) # [(1,2), (2,3), (3,4), (4,5)]
list(zip(a,b,c)) # [(1,2,3), (2,3,4), (3,4,5)]&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;파이썬 아스테리스크 *&lt;/strong&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;별표, 아스테리스크라 부르는 &lt;em&gt;는 *&lt;/em&gt;시퀀스 언패킹 연산자**다. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C의 포인터 변수와 혼동될 수 있지만 파이썬에는 포인터 변수가 존재하지 않는다. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다음과 같이 활용될 수 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;fruits = [&amp;#39;lemon&amp;#39;,&amp;#39;pear&amp;#39;,&amp;#39;watermelon&amp;#39;,&amp;#39;tomato&amp;#39;]
print(*fruits) # lemon pear watermelon tomato&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;위  zip()과 더불어 활용할 수 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;nums = [1,1,1,2,2,3] k = 2

collections.Counter(nums).most_common(k) # [(1,3), (2,2)]
# 언패킹을 하면
list(zip(*collections.Counter(numse).most_common(k))) # [(1,2), (3,2)]
# 언패킹을 하지 않으면
list(zip(collections.Counter(numse).most_common(k))) # [((1,3), (2,2),)]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;함수의 파라미터가 되었을때는 반대로 패킹도 가능하다.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def f(*params):
      print(params)
f(&amp;#39;a&amp;#39;,&amp;#39;b&amp;#39;,&amp;#39;c&amp;#39;)     # (&amp;#39;a&amp;#39;,&amp;#39;b&amp;#39;,&amp;#39;c&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;또 다른 예시. 변수의 할당도 묶어서 처리할 수 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;a, *b = [1,2,3,4]
a # 1
b #[2,3,4]&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;여전히 풀이 코드를 쉽게 읽어낼 순 없지만 조금씩 속도가 올라가는 듯하다. 화이팅.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;abstract data type(ADT)&lt;/strong&gt; 아래 정의를 따르는 데이터 구조의 모델이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;데이터 컬렉션의 속성&lt;/li&gt;
&lt;li&gt;데이터에 대해 수행할 수 있는 작업&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An ADT has two parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;사용자가 볼 수 있는 항목: 개념적 그림(객체, 구조가 어떻게 구성되었는지에 대한 사용자의 견해). 개념 작업(사용자가 ADT에 수행할 수 있는 작업)&lt;/li&gt;
&lt;li&gt;프라이빗 혹은 내부 파트로 구성되어 있습니다. 작업 구현(실제 구조가 어떻게 저장되는지)의 표현(실제 코드)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파이썬 heappush에서 추가 인자 삽입&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Tuple in heappush method args
heappush(h, value)
# Heap elements can be tuples. 
# This is useful for assigning comparison values (such as task priorities)
h = []
heappush(h, (5, &amp;#39;write code&amp;#39;))
heappush(h, (7, &amp;#39;release product&amp;#39;))
heappush(h, (1, &amp;#39;write spec&amp;#39;))
heappush(h, (3, &amp;#39;create tests&amp;#39;))
heappop(h)
(1, &amp;#39;write spec&amp;#39;)
# https://docs.python.org/3/library/heapq.html

# 책 274 페이지 &amp;#39;k개 정렬 리스트 병합&amp;#39; 문제 풀이 중
for lst in lists:
      heapq.heappush(heap, (lst.val, lst))
# TypeError: &amp;#39;&amp;lt;&amp;#39; not supported between instances of ListNOde and ListNode
# (중복된 값을 넣을 수 없다는 에러) 가 있을때 오직 추가 방지만을 위해 추가 인자를 삽입한다.
for lst in range(len(lists)):
      heapq.heappush(heap, (lists[i].val, i, lists[i]))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/북TIL</category>
      <category>데크</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>우선순위큐</category>
      <category>인터뷰</category>
      <category>자료구조</category>
      <category>큐</category>
      <category>파이썬</category>
      <category>해시테이블</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/85</guid>
      <comments>https://devpanda.tistory.com/85#entry85comment</comments>
      <pubDate>Mon, 7 Nov 2022 23:03:46 +0900</pubDate>
    </item>
    <item>
      <title>파이썬알고리즘인터뷰 8장 연결리스트</title>
      <link>https://devpanda.tistory.com/84</link>
      <description>&lt;h3&gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;재귀, 연결리스트 활용 500배&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;2022.10.10~2022.10.14&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파이썬 알고리즘 인터뷰 8장 연결리스트&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;런너 기법- 2칸씩 이동하는 포인터 fast와 느린 런너(1칸씩 이동) slow를 둔다. 빠른 런너가 먼저 리스트 끝에 도달하면, 느린 런너는 리스트의 중간 지점을 가리킨다. 이런 방식으로 &lt;strong&gt;중간 위치를 찾아내면, 값을 비교하거나 뒤집기를 시도하는 등 활용도가 많다.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;아래 파이썬의 변수다중할당 부분&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;def isPalindrome(head):
  # 중략
  rev, rev.next, slow = slow, rev, slow.next
  # 위 다중할당은 아래와 같이 바꿔주면 가독성이 좋다.
  rev, rev.next = slow, rev
  slow = slow.next
  # 두줄로 나눈 위 할당으론 풀수 없다.
  #  rev, rev.next = slow, rev 구문에서 slow와 rev는 동일한 참조가 되어버린다.
  ```
  파이썬에는 원시타입이 존재하지 않고 모든 것이 객체이기에
  &amp;quot;=&amp;quot; 연산자를 사용해 할당하면 값을 할당하지 않고 불변 객체에 대한 참조를 할당하게 된다.
  이를 참고해 위 코드에 대입해 이해해보자
  ```
  # rev = 1, slow = 2-&amp;gt;3 (연결리스트)일때
  rev, rev.next, slow = slow, rev, slow.next
  # 이 경우 rev = 2-&amp;gt;3 , rev.next = 1, slow = 3 이 되고, rev.next = 1 이므로
  # 최종적으로 rev = 2-&amp;gt;1, slow = 3이 된다.
  # 다중 할당으로 위 작업이 동시에 일어나기 때문에 한번의 트랜잭션으로 끝나게 된다.

  # 그러나
  rev, rev.next = slow, rev
  slow = slow.next
  # 위와 같이 두 줄 분기 코드로 나눠서 처리하는 경우
  # 첫줄 실행 결과 rev = 2-&amp;gt;1 이 되고, 
  # 동일한 참조인 rev = slow 가 됐기 때문에 slow 또한 2-&amp;gt;1이 되어버린다.

  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt; &lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;변수다중할당을 쓴 코드 1줄을 이해하기 위해서 파이썬의 = 연산자의 할당 방식, 다른 언어의 원시 타입 등을 찾아봐야했다.&lt;/li&gt;
&lt;li&gt;다르게 말하면, 코드의 가독성을 높이고 효율적인 코드를 짜려면 언어들의 작동 방식, 특성을 잘 이해해야한다는 뜻이 아닐까&lt;/li&gt;
&lt;li&gt;재귀는 어렵다. 함수 호출이 중첩되면서 내려가면 뒤죽박죽이 된다..&lt;/li&gt;
&lt;li&gt;백준을 통해서는 연결리스트와 관련한 문제들을 접하지 못했는데, 책의 리트코드 예제를 통해 연결리스트, 노드를 활용하는 방법을 배울 수 있었다. 실제  연결리스트 구조의 데이터를 처리하려면 단순 노드들의 value만 스왑해주는 식으론 해결할 수 없기에 더 익숙해져야할듯하다.&lt;/li&gt;

&lt;/ul&gt;</description>
      <category>노드</category>
      <category>다중할당</category>
      <category>연결리스트</category>
      <category>재귀</category>
      <category>파이썬</category>
      <category>팰린드롬</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/84</guid>
      <comments>https://devpanda.tistory.com/84#entry84comment</comments>
      <pubDate>Thu, 20 Oct 2022 19:26:45 +0900</pubDate>
    </item>
    <item>
      <title>헤로쿠 503에러 해결 (code=H10 desc=App crashed)</title>
      <link>https://devpanda.tistory.com/83</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;노마드코더에서 youtube 클론코딩 강좌를 듣고 완성 후 heroku를 이용해 배포했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 얼마전 몽고db 아틀라스에서 장기 미활동으로 인해 클러스터를 정지시킨다는 예고 메일이 왔었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.35.59.png&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;952&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dOe63m/btrOAA7kKw3/hfZMNDZpioXfJ89yWJogD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dOe63m/btrOAA7kKw3/hfZMNDZpioXfJ89yWJogD0/img.png&quot; data-alt=&quot;제때 Resume을 눌러줬더라면..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dOe63m/btrOAA7kKw3/hfZMNDZpioXfJ89yWJogD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdOe63m%2FbtrOAA7kKw3%2FhfZMNDZpioXfJ89yWJogD0%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;577&quot; height=&quot;428&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.35.59.png&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;952&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;제때 Resume을 눌러줬더라면..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 클러스터는 자동으로 정지되었고 뒤늦게 배포 사이트를 들어가보니&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.39.21.png&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfOEGX/btrOCJ9erER/mjIWGXALn1E69Zh9w3dtg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfOEGX/btrOCJ9erER/mjIWGXALn1E69Zh9w3dtg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfOEGX/btrOCJ9erER/mjIWGXALn1E69Zh9w3dtg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfOEGX%2FbtrOCJ9erER%2FmjIWGXALn1E69Zh9w3dtg1%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;1052&quot; height=&quot;436&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.39.21.png&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 db가 꺼져버려 정상 접속이 되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 안내 메세지대로 로그를 확인해보니&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.42.00.png&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baMiDH/btrOCdpzCp8/lZcKzIMNjU6pKVwu7BeIAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baMiDH/btrOCdpzCp8/lZcKzIMNjU6pKVwu7BeIAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baMiDH/btrOCdpzCp8/lZcKzIMNjU6pKVwu7BeIAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaMiDH%2FbtrOCdpzCp8%2FlZcKzIMNjU6pKVwu7BeIAK%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;1720&quot; height=&quot;370&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.42.00.png&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 &lt;b&gt;503 에러&lt;/b&gt;를 뱉고있었다. 루트페이지와 파비콘 등 초기 페이지 전체가 정상적으로 처리되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤늦게 &lt;b&gt;mongoDB에 접속해 다시 클러스터를 켜주고&lt;/b&gt; 헤로쿠 환경 변수 DB_URL을 새롭게 업데이트 해줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(몽고디비 클러스터 0를 inactive -&amp;gt; active 해주는 과정에서 db 안 date들이 초기화되었기에 해주었다. 실제 url이 변경되는지 여부를 찾아보았으나 알 수 없었다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.44.43.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;860&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDJtsS/btrOAzObLp0/UMve0hujKKWZtzdKWhpFmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDJtsS/btrOAzObLp0/UMve0hujKKWZtzdKWhpFmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDJtsS/btrOAzObLp0/UMve0hujKKWZtzdKWhpFmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDJtsS%2FbtrOAzObLp0%2FUMve0hujKKWZtzdKWhpFmK%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;1556&quot; height=&quot;860&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.44.43.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;860&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 클러스터를 다시 active로 만들어준 후 헤로쿠 CLI&amp;nbsp; `heroku restart` 명령어를 통해 헤로쿠 서버를 재시작했더니&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;TIP&amp;nbsp;By default&amp;nbsp;heroku restart&amp;nbsp;will restart&amp;nbsp;all&amp;nbsp;of your dynos, but you can specify a specific dyno to restart (e.g.&amp;nbsp;heroku ps:restart web.1), or all dynos of a specific type (e.g.&amp;nbsp;heroku ps:restart web).&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.58.32.png&quot; data-origin-width=&quot;3696&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mZinT/btrOzgnSGGE/CcSb7XegUaEKBBawOiZGJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mZinT/btrOzgnSGGE/CcSb7XegUaEKBBawOiZGJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mZinT/btrOzgnSGGE/CcSb7XegUaEKBBawOiZGJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmZinT%2FbtrOzgnSGGE%2FCcSb7XegUaEKBBawOiZGJk%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;3696&quot; height=&quot;536&quot; data-filename=&quot;스크린샷 2022-10-14 오후 3.58.32.png&quot; data-origin-width=&quot;3696&quot; data-origin-height=&quot;536&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;&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;헤로쿠 코드 H10 해결을 위해 구글링해보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 express port를 heroku &lt;b&gt;환경변수(process.env.PORT)로 주지 않아 발생한 경우가 많았다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 내 경우는 port 환경 변수가 잘 설정되어 있었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몽고디비 클러스터가 정지되면서 DB와 연결이 끊어져 생긴 일이라 생각해 위와 같이 문제를 해결했다.&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>503</category>
      <category>노드js</category>
      <category>배포</category>
      <category>익스프레스</category>
      <category>자바스크립트</category>
      <category>헤로쿠</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/83</guid>
      <comments>https://devpanda.tistory.com/83#entry83comment</comments>
      <pubDate>Fri, 14 Oct 2022 16:07:32 +0900</pubDate>
    </item>
    <item>
      <title>타입스크립트 angle brackets, 꺾쇠 괄호 &amp;lt;&amp;gt;</title>
      <link>https://devpanda.tistory.com/80</link>
      <description>&lt;h2&gt;타입스크립트의 angle brackets, 꺾쇠 괄호 &amp;lt;&amp;gt;&lt;/h2&gt;
&lt;p&gt;노마드코더 타입스크립트 10일차 과제는 abstract classes, generics 그리고 overloading 을 이용해 fake API를 만드는 과제다.&lt;/p&gt;
&lt;p&gt;과제를 진행하는도중 타입스크립트의 &lt;strong&gt;다양한 타입 형태가 나를 헷갈리게 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-tsx' lang='tsx'&gt;abstract class AbLocationStroage&amp;lt;T&amp;gt; {
    [key: string]: T
}

/// LocalStorage를 흉내낸 class
class LocalStorageAPI&amp;lt;T&amp;gt; {
    private stroage: AbLocationStroage&amp;lt;T&amp;gt; = {}
}
		setItem(key: string, value: T) {
        if (this.stroage[key]) {
            console.log(`${key} already exists.`)
        }
        else {
            this.stroage[key] = value
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;스토리지 생성자의 AbLocationStorage에 붙은 &lt;strong&gt;&lt;T&gt;는 추상클래스의 제네릭이고,&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;setItem의 2번째 인자 타입의 T는 LocalAPI클래스의 제네릭을 받아온다..라고는 이해했지만,&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;제네릭 외에 tsx를 쓰다보면 꺾쇠가 자주 보여 혼동되기에 정리해보았다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;타입스크립트의 &amp;lt; SOMETHING &amp;gt; 문법은 다음과 같이 쓰인다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;h4&gt;Type Parameters&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;타입파라미터는 제네릭 형식 참조 또는 제네릭 함수 호출에서 바인딩되는 실제 유형을 나타냅니다 &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;클래스, 인터페이스, 함수들의 콜시그니쳐와 정의에 쓰인다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-typescript' lang='typescript'&gt;function heat&amp;lt;T&amp;gt;(foot:T): T {
          //^^^^^ Type parameter list
  return food;
}
class Pizza&amp;lt;T, E extends Cheese&amp;gt; {
           //^^^^^^^^^^^^^^^^^ Type parameter list
  toppingA:T;
  toppingB:E;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;  &lt;br/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;h4&gt;Type Arguments&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;제네릭 타입과 제네릭 함수를 레퍼런스한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-tsx' lang='tsx'&gt;var pizza: Pizza&amp;lt;Pepperoni, Mozzarella&amp;gt;; 
            //^^^^^^^^^^^^^^^^^^^^^^^ Type argument list
pizza = heat&amp;lt;{toppingA: Pepperonu, topingB: Mozzarella}(ingredients)
             //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Type argument list
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Parameter는 함수 정의에 있는 변수&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Argument는 함수에 실제로 전달되는 값이다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type Parameter는 제네릭에서 타입 선언에 대한 blue print, place holder.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type Arguments는 제네릭을 parameterize하는데 사용되는 실제 타입이다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;ol start='3' &gt;
&lt;li&gt;&lt;h3&gt;Type Assertions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;TypeScript에서는 시스템이 추론 및 분석한 타입 내용을 우리가 원하는 대로 얼마든지 바꿀 수 있습니다. 이때 &amp;quot;타입 표명(type assertion)&amp;quot;이라 불리는 메커니즘이 사용됩니다. TypeScript의 타입 표명은 프로그래머가 컴파일러에게 내가 너보다 타입에 더 잘 알고 있고, 나의 주장에 대해 의심하지 말라고 하는 것과 같습니다.&lt;/em&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;공식문서에서 봤을때 가장 이해가 안되었던 부분. UnaryExpression(단항표현식) 으로 정의되고 사용된다. 주로 자바스크립트를 타입스크립트로 포팅할때 사용되는 경우가 많다고 한다. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;타입스크립트에서 훅을 사용할때 타입에러를 뱉는경우&lt;/strong&gt; &lt;code&gt;as&lt;/code&gt; &lt;strong&gt;로 처리했던 경우를 떠올리면 될듯..&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-tsx' lang='tsx'&gt;var foo = {};
foo.bar = 123; // 오류: 속성 &amp;#39;bar&amp;#39;가 `{}`에 존재하지 않음
foo.bas = &amp;#39;hello&amp;#39;; // 오류: 속성 &amp;#39;bar&amp;#39;가 `{}`에 존재하지 않음

//// 위와 같은 상황에서
interface Foo {
    bar: number;
    bas: string;
}
/// 인터페이스를 추가해주고 
var foo = {} as Foo;
//// foo 의 타입을 as를 통해 Foo 표명해주면
foo.bar = 123;
foo.bas = &amp;#39;hello&amp;#39;; // Ok.
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;위와 같은 방식엔 꺾쇠를 사용하지 않는다. 그렇다면 왜 이 항목에?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실제로는 꺾쇠를 사용한 syntax를 썼어야하는데, &lt;strong&gt;JSX에서 문법적으로 모호해지기에&lt;/strong&gt; &lt;code&gt;as Foo&lt;/code&gt; 와 같이 사용하는 것이 권장된다고 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-tsx' lang='tsx'&gt;// 본래 권장되던 방식
var foo: any;
var bar = &amp;lt;string&amp;gt; foo;  // 이제 bar의 타입은 &amp;quot;문자열&amp;quot;입니다
      
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-tsx' lang='tsx'&gt;// 아래와 같은 JSX에서 component인지 type assertion인지 문법적으로 모호해진다.
var foo = &amp;lt;string&amp;gt;bar;
&amp;lt;/string&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;마지막으로 jsx 표현이다. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;documented 된 스펙은 아니다. &lt;code&gt;&amp;lt;JSXElementName JSXAttributes(optional) /&amp;gt;&lt;/code&gt; 으로 쓴다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;  &lt;br/&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;공부를 하고나니 , 첫 코드에 쓰인 T들을 설명할수 있게 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-tsx' lang='tsx'&gt;abstract class AbLocationStroage&amp;lt;T&amp;gt; {
  //                            ^^^  Type paramter
    [key: string]: T
  //              ^^^ Type -capture the one the user provides
}

class LocalStorageAPI&amp;lt;T&amp;gt; {
    //               ^^^  Type paramter
    private stroage: AbLocationStroage&amp;lt;T&amp;gt; = {}
  //                                  ^^^  Type paramter
}
		setItem(key: string, value: T) {
			//                       ^^^  Type
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href='https://stackoverflow.com/questions/37358364/rules-for-the-use-of-angle-brackets-in-typescript'&gt;참고한 Stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[타입스크립트딥다이브&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <category>꺾쇠</category>
      <category>제네릭</category>
      <category>타입스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/80</guid>
      <comments>https://devpanda.tistory.com/80#entry80comment</comments>
      <pubDate>Wed, 28 Sep 2022 19:31:24 +0900</pubDate>
    </item>
    <item>
      <title>Framer-motion 리액트 애니메이션 라이브러리</title>
      <link>https://devpanda.tistory.com/79</link>
      <description>&lt;h3&gt;Framer-motjon&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;리액트를 위한 오픈소스 프로덕션레디 모션 라이브러리 &lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;프로덕션 레디란? &lt;/p&gt;
&lt;p&gt;사용자의 요구-사용성, 의존성, 가용성-을 충족 시키는 소프트웨어. 실제 운영 환경에서 구동이 가능한 코드.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;
&lt;li&gt;&lt;h5&gt;&lt;strong&gt;설치&lt;/strong&gt;&lt;/h5&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;npm install framer-motion&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;import { motion } from &amp;quot;framer-motion&amp;quot;

export const MyComponent = ({ isVisible }) =&amp;gt; (
    &amp;lt;motion.div animate={{ opacity: isVisible ? 1 : 0 }} /&amp;gt;
)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h4&gt;&lt;strong&gt;Animations&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Motion 컴포넌트를 animate 속성을 통해 제어하며, 간단한 애니메이션은 animate props에서 직접 값을 설정할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;&amp;lt;motion.div animate={{ rotate: 360 }} transition={{ duration: 2 }}&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h4&gt;&lt;strong&gt;Gestures&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;제스쳐는 리액트 이벤트 시스템을 확장하여 사용하며 호버, 탭, 드래그를 지원합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;&amp;lt;motion.div
  whileHover={{ scale: 1.2 }}
  whileTap={{ scale: 1.1 }}
  drag=&amp;quot;x&amp;quot;
  dragConstraints={{ left: -100, right: 100 }}
/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h4&gt;&lt;strong&gt;Variants&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Variants를 통해 애니메이션의 하위 트리를 하나의 animate prop으로 표현할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;const list = { hidden: { opacity: 0 } }
const item = { hidden: { x: -10, opacity: 0 } }

return (
  &amp;lt;motion.ul animate=&amp;quot;hidden&amp;quot; variants={list}&amp;gt;
    &amp;lt;motion.li variants={item} /&amp;gt;
    &amp;lt;motion.li variants={item} /&amp;gt;
    &amp;lt;motion.li variants={item} /&amp;gt;
  &amp;lt;/motion.ul&amp;gt;
)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h4&gt;&lt;strong&gt;MotionValues&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MotionValues는 애니메이션 값의 상태와 속도를 추적합니다. 모든 모션 컴포넌트는 내부적으로 MotionValues를 사용하여 애니메이션 값의 상태와 속도를 추적합니다. 일반적으로 이들은 자동으로 생성됩니다. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MotionValue는 React State가 아니기 때문에 Motion Value값이 바뀌어도 리랜더링이 일어나지 않는다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;import { motion, useMotionValue } from &amp;quot;framer-motion&amp;quot;

export function MyComponent() {
const x = useMotionValue(0)
const input = [-200, 0, 200]
const output = [0, 1, 0]
const opacity = useTransform(x, input, output)
// const potato = useTransform(x, [-200, 0, 200], [0, 1, 0])

return &amp;lt;motion.div drag=&amp;quot;x&amp;quot; style={{ x, opacity }} /&amp;gt;
// 요 컴포넌트의 움직임(X값)에 따라 opacity가 결정된다.&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;useMotionValue()&lt;/code&gt; useMotionValue 후크로 MotionValues를 생성할 수 있습니다. useMotionValue에 전달된 값은 MotionValue의 초기 상태로 작동합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;useTransform 훅을 통해 MotionValues를 연결합니다.&lt;br&gt;useTransform()는 한 값 범위에서 다른 값 범위로 매핑하여 다른 MotionValue의 output을 변환하는 MotionValue를 만듭니다.&lt;br&gt;x(Motion Value)값을 다른 output값으로 변환해줍니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;반응형 웹이 잘 구성된 페이지에선 스크롤 경험도 재밌었는데 요 모션밸류에 useScroll()을 사용하면 스크롤에 따른 애니메이션이 구성가능하다. useScroll은 뷰포트가 스크롤될 때 업데이트되는 MotionValues를 리턴합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;scrollX&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;수평 스크롤 픽셀&lt;/th&gt;
&lt;th&gt;ex)500px&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;scrollY&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;수직 스크롤 픽셀&lt;/td&gt;
&lt;td&gt;ex)500px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;scrollXProgress&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0~1사이값 수평스크롤&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;scrollYProgress&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0~1사이값 수직스크롤&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;export const MyComponent = () =&amp;gt; {
const { scrollYProgress } = useViewportScroll()
return &amp;lt; motion.div style={{ scaleX: scrollYProgress }} /&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h4&gt;&lt;strong&gt;Orchestration&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;기본적으로 모든 애니메이션은 동시에 시작됩니다. 그러나 variants를 사용하면 &lt;code&gt;when, delayChldren, sttagerChildren&lt;/code&gt;과 같은 prop들을 사용할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;-delayChildren: 딜레이 시간 후에 하위 애니메이션이 시작됩니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;staggerChildren: 하위 컴포넌트의 애니메이션에 지속 시간(초)만큼 시차를 둘 수 있습니다. 예를 들어, staggerChildren이 0.01이면 첫 번째 자식은 0초, 두 번째 자식은 0.01초, 세 번째 자식은 0.02초 지연되는 식입니다. &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/자바스크립트</category>
      <category>리액트</category>
      <category>애니메이션</category>
      <category>타입스크립트</category>
      <category>프레이머모션</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/79</guid>
      <comments>https://devpanda.tistory.com/79#entry79comment</comments>
      <pubDate>Fri, 23 Sep 2022 20:03:34 +0900</pubDate>
    </item>
    <item>
      <title>[타입스크립트] CRA를 활용하지 않은 TS프로젝트 생성</title>
      <link>https://devpanda.tistory.com/78</link>
      <description>&lt;p&gt;CRA를 사용하지 않고 타입스크립트 프로젝트를 생성하기&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;콘솔창에 &lt;code&gt;npm init -y&lt;/code&gt; 를 입력, package.json 파일 생성&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm i -D typescript&lt;/code&gt; 입력, devDependency에 타입스크립트 추가&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;타입스크립트 설정 파일 tsconfig.json 생성&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;이 파일을 통해 vscode는 TS로 작업하는 것을 감지하고 자동완성을 제공한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-json' lang='json'&gt;{
  /* Directories for compiled JS */
  &amp;quot;include&amp;quot;:[
    &amp;quot;src&amp;quot; 
  ],
  &amp;quot;compilerOptions&amp;quot;:{
    &amp;quot;outDir&amp;quot; : &amp;quot;build&amp;quot;,  /* Product will be located at */
    &amp;quot;target&amp;quot;:&amp;quot;ES6&amp;quot;, /* Product will be compiled in ES6 */
    &amp;quot;lib&amp;quot;: [&amp;quot;ES6&amp;quot;, &amp;quot;DOM&amp;quot;]
    /* Describe runtime env(platform) */
    /* then, TS will help you with auto-complete*/
    /* ex) documnet.querySelector */
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href='https://www.typescriptlang.org/tsconfig'&gt;TSConfig reference&lt;/a&gt; &lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;대부분은 definitelyTyped에서 찾지만, 공부를 위해서 직접 declaration을 한다면&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;type definition file&lt;/strong&gt;(d.ts) 을 통해 타입 정의를 따로 해줄 경우. &lt;/li&gt;

&lt;/ol&gt;
&lt;pre&gt;&lt;code class='language-javascript' lang='javascript'&gt;/// myPackage.js
export function init(config) {
  return true;
}

export function exit(code) {
  return code + 1;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class='language-typescript' lang='typescript'&gt;/// index.ts 에 이렇게 import 하려면
import { init, exit  } from &amp;quot;myPackage&amp;quot;;

/// Could not find a declaration file for module 라는 에러가 뜬다.

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class='language-typescript' lang='typescript'&gt;/// myPackage.d.ts 파일을 생성
/// 아래와 같이 declaration을 선언한다.
interface Config {
  debug: boolean;
  url: string;
}
declare module &amp;quot;myPackage&amp;quot; {
  function init(config: Config): boolean;
  function exit(code: number): number;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;ol start='2' &gt;
&lt;li&gt;&lt;p&gt;프로젝트 안에 js, ts가 같이 존재하는 경우에는 tsconfig에 &lt;code&gt;allowJs:true&lt;/code&gt;로 설정해준 후 JS파일을 import 하면 된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JS를 그대로 사용하되, 타입스크립트의 보호를 받으려면 JSDoc을 활용할 수 있다. 이 경우 주석을 활용해 type 보호를 받을 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-javascript' lang='javascript'&gt;// JSDoc 코멘트를 활용해 타입보호를 받을수 있다.

// @ts-check
/**
 * initailizes the project
 * @param {object} config
 * @param {boolean} config.debug
 * @param {string} config.url
 * @returns {boolean}
 */
export function init(config) {
  return true;
}

/**
 * Exits the program
 * @param {number} code
 * @returns   
 */
export function exit(code) {
  return code + 1;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/li&gt;

&lt;/ol&gt;</description>
      <category>개발/자바스크립트</category>
      <category>d.ts</category>
      <category>jsdoc</category>
      <category>tsconfig</category>
      <category>자바스크립트</category>
      <category>타입스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/78</guid>
      <comments>https://devpanda.tistory.com/78#entry78comment</comments>
      <pubDate>Fri, 26 Aug 2022 19:04:15 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 파이썬 알고리즘 인터뷰 7장 배열</title>
      <link>https://devpanda.tistory.com/77</link>
      <description>&lt;h3&gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;브루트포스, 투포인터는 생각보다 다양한 풀이에서 써먹을 수 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;그러나 두 방법보다 효율이 좋은 풀이도 존재한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파이썬은 쓰기 쉬운 언어다. 그러나 Go나 C(++)에 비해 성능이 부족한걸 기억하고 푼다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt; &lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;2020 08.05. FRI. ~ 08.11. THU&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬 알고리즘 인터뷰 7장 배열&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;추상자료형(ADT)의 실제 구현 대부분은 배열 또는 연결 리스트를 기반으로 한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파이썬과 같은 동적 프로그래밍 언어는 정적 배열 자체를 제공하지 않는다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;동적 배열은 미리 초깃값을 작게 잡아 배열을 생성하고, 데이터가 추가되면서 꽉 채워지면 늘려주고 복사하는 식이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;비교, 탐색을 쓰지 않는 &lt;em&gt;두 수의 합&lt;/em&gt; 풀이 // &lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;# 덧셈하여 타겟을 만들 수 있는 두 숫자 인덱스를 리턴하라
# 입력값
nums = [2,7,11,15], target = 9 
# 풀이
def twoSum(self, nums:list[int], target:int) -&amp;gt; list[int]:
    nums_map = {}
    # 키와 값을 딕셔너리로 바꿔서 저장
    for i, num in enumerate(nums):
        nums_map[num] = i
    
    # 타겟에서 첫 번째 수를 뺀 결과를 키로 조회
    for i, num in enumerate(nums):
        if target - num in nums_map and i != nums_map(target-num):
            return [i, nums_map[target-num]]
          
### 위 for 문을 합친다면 
def twoSum(self, nums:list[int], target:int) -&amp;gt; list[int]:
    nums_map = {}
    for i, num in enumerate(nums):
        if target - num in nums_map:
            return [nums_map[target-num], i]
        nums_map[num] = i
        # 타겟이 4,14,22 등과 같이 리스트 요소를 중복 사용하여 더할 수 있는 경우의 예외처리가 중요한데
				# target-num 값을 넘스맵과 비교하고 난 후 넘스맵에 붙이는 형식으로 이를 처리한 점이 인상적이다.
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;최댓값, 최솟값을 &lt;code&gt;sys.maxsize&lt;/code&gt; 로 지정하는 부분이 신박했다. None으로 잡아둘 경우 비교할 수 없고 일반적으로 선언하는 0보다 안전하다.&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;알고리즘 문제 풀이와 구현을 보다보면, 그 연결 고리가 이해가 되지 않을때가 있다. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예를들면, 리트코드 42번 빗물 트래핑 문제에서 스택을 활용한 풀이가 있다.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;quot;변곡점을 만날 때마다 스택에서 하나씩 꺼내면서 이전과의 차이만큼 물 높이를 채워 나간다&lt;/em&gt; &amp;quot; 가 풀이의 핵심인데, 구현을 보면&lt;/li&gt;
&lt;li&gt;distance 와 waters 를 각각 구해서 곱을 volume에 더해주는데 distance가 왜 구현됐는지 내 머리로는 아직 이해가 안되는 것이다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;예제 인풋값을 넣어보면 결국 답이 나옴을 이해하지만, 사실 이런 피상적인 이해로 문제가 주어졌을때 내가 풀어낼수 있을까 하는 의문이 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;간단한(그러나 생각해내기 어려운) 예외처리가 코드의 질을 높인다는 것을 다시한번 상기하게 되었다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Python method 속의 self 역할?&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;[파이썬에는] 메서드에서 객체의 멤버를 참조하는 약어가 없습니다. 메서드 함수는 호출에 의해 암시적으로 제공되는 객체를 나타내는 명시적 첫 번째 인수로 선언됩니다.&lt;/p&gt;
&lt;p&gt;종종 메서드의 첫 번째 인수를 self라고 합니다. 이것은 관례에 불과합니다. self라는 이름은 파이썬에 전혀 특별한 의미가 없습니다. 그러나 규칙을 따르지 않으면 가독성이 떨어질 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;&amp;#39;&amp;#39;&amp;#39;
Let&amp;#39;s say you have a class ClassA which contains a method methodA defined as:
&amp;#39;&amp;#39;&amp;#39;
def methodA(self, arg1, arg2):
    # do something

&amp;#39;&amp;#39;&amp;#39;
and ObjectA is an instance of this class.

Now when 
# ObjectA.methodA(arg1, arg2) # is called, 
python internally converts it for you as:
&amp;#39;&amp;#39;&amp;#39;
ClassA.methodA(ObjectA, arg1, arg2)

# The SELF variable refers to the object ITSELF.
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;</description>
      <category>개발</category>
      <category>배열</category>
      <category>브루트포스</category>
      <category>상길북</category>
      <category>알고리즘</category>
      <category>투포인터</category>
      <category>파이썬</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/77</guid>
      <comments>https://devpanda.tistory.com/77#entry77comment</comments>
      <pubDate>Thu, 11 Aug 2022 14:27:32 +0900</pubDate>
    </item>
    <item>
      <title>[타입스크립트] Call Signatures</title>
      <link>https://devpanda.tistory.com/76</link>
      <description>&lt;blockquote&gt;&lt;p&gt;TS의 다양한 함수 표현 중 Call signiture에 대해 찾아보던 중, TS핸드북의 예제 코드가 이해되지 않았다.&lt;/p&gt;
&lt;p&gt;스택오버플로우의 친절한 설명덕에 이해할 수 있어 정리해본다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Call Signitures&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;타입스크립트에서, interface로 function을 정의하는 것은 콜 시그니쳐를 추가해주면 가능해진다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-typescript' lang='typescript'&gt;type Add = (a:number, b:number) =&amp;gt; number;

const add:Add = (a,b) =&amp;gt; a+b
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;프로퍼티로 호출 가능한 것을 설명하려면 객체 타입에 Call Signature을 작성할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call Signatures는 다음과 같이 함수의 매개 변수(parameter)와 반환 타입을 지정합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-javascript' lang='javascript'&gt;// JS에서는 fucntion도 object이기 때문에 function 자체가 
// callable해 함수에 추가 property를 가질 수 있다.

const func = () =&amp;gt; {
  return 123;
}
func.a = &amp;#39;a&amp;#39;;
console.log(func.a)
console.log(func())
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class='language-typescript' lang='typescript'&gt;// 그러나 타입스크립트의 경우에는 미리 선언된 파라미터, 반환 타입 외
// 새로운 property가 호출될 수 없다.
// 그러나 콜시그니쳐를 이용하면 가능하다.

type DescribableFunction = {
    description: string;
    (someArg: number): boolean;
};

function doSomething(fn: DescribableFunction) {
    console.log(fn.description + &amp;quot; returned &amp;quot; + fn(6));
}
// 여기까지가 TS 핸드북 예제
// 위 콜 시그니쳐를 이해하기 위해 greaterThanTen 함수를 정의해본다
function greaterThanTen(someArg: number) {
    return someArg &amp;gt; 10;
}

// DescribableFunction 콜 시그니쳐를 통해 아래 호출이 가능하다.
greaterThanTen.description = &amp;quot;greaterThanTen&amp;quot;;
doSomething(greaterThanTen); // &amp;quot;greaterThanTen returned false&amp;quot; 


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;</description>
      <category>개발/자바스크립트</category>
      <category>콜시그니쳐</category>
      <category>타입스크립트</category>
      <category>함수</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/76</guid>
      <comments>https://devpanda.tistory.com/76#entry76comment</comments>
      <pubDate>Tue, 9 Aug 2022 23:12:48 +0900</pubDate>
    </item>
    <item>
      <title>[네트워크] IP 주소와 서브네팅</title>
      <link>https://devpanda.tistory.com/75</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;IP 주소란?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터넷 주소로 전 세계 주소를 IANA에서 대륙별로 할당, 관리한다.&lt;/li&gt;
&lt;li&gt;네트워크 장비 식별을 위해 고유한 IP 주소 사용&lt;/li&gt;
&lt;li&gt;32bit로 이루어진 주소 (약 43억개)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;bit는 2진수 한자리(0 or 1)&lt;/li&gt;
&lt;li&gt;2진수 8자리를 묶어서 1Byte 혹은 1옥텟이라 부름&lt;/li&gt;
&lt;li&gt;1옥텟은 8비트로 2^8이 되니 32bit인 IP주소 개수는 2^32으로 약 43억개&lt;/li&gt;
&lt;li&gt;따라서 0.0.0.0 ~ 255.255.255.255(호스트ID) 까지 사용!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실제 네트워크 장비는 IP주소로 2진수를 사용하지만 사람이 볼때는 10진수로 변환해 표기(Dotted Decimal Notation)&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;IP 주소 Class&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;A 클래스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 한 비트는 항상 0 -&amp;gt; 따라서 십진수로 1~127&lt;/li&gt;
&lt;li&gt;그러나 첫 옥텟이 0과 127로 시작하는 주소는 예약이 되어있어 1~126까지가 클래스A&lt;/li&gt;
&lt;li&gt;첫 8비트를 네트워크 ID로 사용하기 때문에 호스트 ID는 2^24로 약 1670만개의 개수를 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;B 클래스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 두 비트는 항상 10으로 고정(128~191)&lt;/li&gt;
&lt;li&gt;두 옥텟을 네트워크 ID로 사용하기에 호스트 ID 개수는 2^16 = 65536개&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;C 클래스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 세 비트는 110(192~223)&lt;/li&gt;
&lt;li&gt;첫 세 옥텟을 네트워크 ID로 사용하기에 호스트 ID 개수는 256개&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A, B, C 는 가용한 호스트 ID 개수를 통해 알 수 있듯 각각 대, 중, 소형 네트워크에 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D는 멀티캐스트 통신을 위해, E는 연구용을 위해 사용되는 주소다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호스트 ID가 모두 0인 주소는 네트워크를 나타내는 네트워크 주소이고, 모두 1인 주소는 네트워크의 모든 호스트로 데이터를 전달하기 위한 브로드캐스트 주소다. (사용할 수 없다.)&lt;/p&gt;
&lt;/blockquote&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;IP주소에서 네트워크 ID와 호스트ID를 구분하기 위해 사용&lt;/li&gt;
&lt;li&gt;32 비트로 구성되어 있으며 표기법 또한 IP주소와 동일&lt;/li&gt;
&lt;li&gt;네트워크 ID는 1로, 호스트 ID는 0으로 표기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A 클래스 - 255.0.0.0&lt;/li&gt;
&lt;li&gt;B 클래스 - 255.255.0.0&lt;/li&gt;
&lt;li&gt;C클래스 - 255.255.255.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Prefix를 통해 다른 방법으로 표현할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP 주소 뒤에 네트워크 ID 비트 개수를 나타내면 된다.&lt;/li&gt;
&lt;li&gt;클래스 A의 경우 10.10.10.10 &lt;i&gt;&lt;b&gt;/ 8&lt;/b&gt;&lt;/i&gt; 로 표기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Subneting&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP 주소를 효율적으로 나누어 사용하기 위한 방법&lt;/li&gt;
&lt;li&gt;50개의 호스트 ID가 필요한 네트워크를 구성해야할 때, C 클래스를 이용해 64개씩 4개의 호스트 ID를 구성한다면 버려지는 IP주소를 최대한 줄여 다른 네트워크에 활용할 수 있다.&lt;/li&gt;
&lt;li&gt;이때 호스트 ID의 왼쪽 부터 &lt;b&gt;서브넷 구분 비트&lt;/b&gt;를 할당해 서브넷팅한다.&lt;/li&gt;
&lt;li&gt;예를 들어 192.168.10.0 / 24 의 C 클래스 IP 주소를 절반으로 나누려 한다면, 다음과 같다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;먼저 2진수로 풀어쓴다.&lt;/li&gt;
&lt;li&gt;호스트 ID의 비트 하나만 서브넷 구분 비트로 할당한다.&lt;/li&gt;
&lt;li&gt;0~127 // 128~255 두 개의 그룹으로 나누어진다. 중요한 것은 서브넷 구분비트까지 네트워크 ID에 들어가는데, &lt;i&gt;&lt;b&gt;이에 따라 0과 128은 네트워크 주소 /. 127, 255 는 브로드캐스트 주소가 된다&lt;/b&gt;&lt;/i&gt; 직접 이진수로 표현해보면 쉽게 이해된다.&lt;/li&gt;
&lt;li&gt;따라서 실제 장비에 할당 가능한 주소는 1~126, 129~254까지만 가능하다.&lt;/li&gt;
&lt;li&gt;또 서브넷 마스크를 표현할 때 서브넷 구분 비트까지 표현해주어야 한다. 위의 경우는 255.255.255.128 프리픽스로는 / 25&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C 클래스 주소를 64개씩 4개로 서브네팅하려면 서브넷 구분 비트를 2개를 주면 된다. 주의할 점은 네트워크 주소, 브로드캐스트 주소와 S/M 표기일 것이다.&lt;/li&gt;
&lt;li&gt;서브네팅을 이해하고 있다면, 주소 나누기와 호스트 ID 범위 구하기가 가능해야 할 것!&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/네트워크</category>
      <category>cs</category>
      <category>iP</category>
      <category>네트워크</category>
      <category>서브네팅</category>
      <category>서브넷마스크</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/75</guid>
      <comments>https://devpanda.tistory.com/75#entry75comment</comments>
      <pubDate>Fri, 29 Jul 2022 10:52:03 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 파이썬알고리즘인터뷰 6. 문자열 조작</title>
      <link>https://devpanda.tistory.com/74</link>
      <description>&lt;h3&gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;깔끔하고 빠른 코드를 위해선 &lt;em&gt;&lt;strong&gt;리스트 컴프리헨션, 람다 표현식, 정규식&lt;/strong&gt;&lt;/em&gt;을 잘 다룰줄 알아야 함.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python의 유용한 메서드는 반드시 기억&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;같은 기능을 필요로 할때, 처리시간이 빠른 방법을 택하려면 결국 메서드 실행 시간을 알아야함.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ex- 문자열 슬라이싱 &amp;gt; reverse() &amp;gt; reversed()+join() &amp;gt; for 반복 &amp;gt; while반복 &amp;gt; 재귀(슬라이싱의54배)&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;2022.07.21. THU ~ 07.27 WED&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬알고리즘인터뷰 - 6장 문자열조작&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;isalnum()&lt;/code&gt; &lt;code&gt;isdigit()&lt;/code&gt;:숫자 여부인지 판별해준다. &lt;em&gt;실수나 음수는 판단불가해서 False 반환&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;a = &amp;quot;1&amp;quot;
b = &amp;quot;english&amp;quot;
a.isalnum() # True
b.isalnum() # True
a.isdigit() # True
b.isdigit() # False

c = 1
# c는 int 형태이기에 아래 에러를 띄우면서 메소드 사용이 불가하다.
# AtttributeError:&amp;#39;int&amp;#39; object has no attribute &amp;#39;~&amp;#39;
c.isalnum() 
c.isdigit()

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sort와 람다의 활용&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;s = [&amp;#39;2 A&amp;#39;, &amp;#39;1 B&amp;#39;, &amp;#39;4 C&amp;#39;, &amp;#39;1 A&amp;#39;]
# sort()를 쓴다면 앞의 각 요소의 맨 앞 문자로 정렬하기에 [&amp;#39;1 A&amp;#39;, &amp;#39;1 B&amp;#39;, &amp;#39;2 A&amp;#39;, &amp;#39;4 C&amp;#39;]로 정렬된다.
# 뒤의 알파벳을 우선으로 정렬하려면 람다 표현식을 쓰면된다.
s.sort(key=lambda x: (x.split()[1], x.split()[0])) 
# 결과 - [&amp;#39;1 A&amp;#39;, &amp;#39;2 A&amp;#39;, &amp;#39;1 B&amp;#39;, &amp;#39;4 C&amp;#39;]

# 람다 표현식 없이 sort()로 함수를 선언한다면
def func(x):
    return x.split()[1], x.split()[0]
s.sort(key=func)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;퀵정렬은 데이터에 따라 편차가 크다. 병합은 안정적 성능을 보인다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파이썬의 sorted() 에서 쓰이는 팀소트는 &amp;#39;데이터는 대부분 이미 정리되어 있을 것이다&amp;#39;라는 가정에서 출발, 삽입과 병합 정렬을 휴리스틱하게 조합해 사용하는 정렬 알고리즘이다.&lt;/p&gt;
&lt;figure&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;시간복잡도&lt;/th&gt;&lt;th style='text-align:center;' &gt;최선&lt;/th&gt;&lt;th style='text-align:center;' &gt;평균&lt;/th&gt;&lt;th style='text-align:center;' &gt;최악&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;퀵&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;td style='text-align:center;' &gt;&lt;em&gt;&lt;strong&gt;n^2&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;병합&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;팀소트&lt;/td&gt;&lt;td style='text-align:center;' &gt;&lt;em&gt;&lt;strong&gt;n&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;td style='text-align:center;' &gt;n log n&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;그룹 애너그램의 풀이 원리는 정렬된 값이 같음을 이용하는 것이다. 백준을 풀 때(특히 하노이탑)도 느꼈지만, 결국 문제를 풀어낼 수 있는 핵심 원리를 파악해야 구현도 가능하다는 것이다. 물론 브루트포스와 같이 원리라 부를만한 풀이가 없는 문제들도 잘 파악해야 하겠지만..&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;151페이지 &amp;lt;가장 흔한 단어&amp;gt; 의 이해가 어려웠다. 이해한 과정을 기록해본다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;paragraph = &amp;quot;Bob hit a ball, the hit BALL flew far after it was hit&amp;quot;
banned = [&amp;quot;hit&amp;quot;]

def mostCommonWord(self, paragraph: str, banned: List[str]) -&amp;gt; str:
  	word_f = [word for word in re.sub(r&amp;#39;[^\w]&amp;#39;,&amp;#39; &amp;#39;, paragraph)]
    # 정규식에 따라 단어 문자 아닌 문자 공백 치환
    # p = re.sub(r&amp;#39;[^\w]&amp;#39;,&amp;#39; &amp;#39;, paragraph) 일 경우
    # &amp;#39;Bob hit a ball  the hit BALL flew far after it was hit&amp;#39; 을 리턴함
    # 따라서 list는 아래와 같다.
    # [&amp;#39;B&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39; &amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;i&amp;#39;, &amp;#39;t&amp;#39;, &amp;#39; &amp;#39;, &amp;#39;a&amp;#39;, &amp;#39; &amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39; &amp;#39;,...]
    
    word_s = [word for word in re.sub(r&amp;#39;[^\w]&amp;#39;,&amp;#39; &amp;#39;, paragraph).lower()]
	 	# word_f 요소 중 대문자-&amp;gt;소문자로 변환
		# [&amp;#39;b&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39; &amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;i&amp;#39;, &amp;#39;t&amp;#39;, &amp;#39; &amp;#39;, &amp;#39;a&amp;#39;, ...]
              
    word_t = [word for word in re.sub(r&amp;#39;[^\w]&amp;#39;,&amp;#39; &amp;#39;, paragraph).lower().split()]
    # re.sub(r&amp;#39;[^\w]&amp;#39;,&amp;#39; &amp;#39;, paragraph).lower().split() 의 반환값은
    # [&amp;#39;bob&amp;#39;, &amp;#39;hit&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;ball&amp;#39;, &amp;#39;the&amp;#39;, &amp;#39;hit&amp;#39;, &amp;#39;ball&amp;#39;, &amp;#39;flew&amp;#39;, &amp;#39;far&amp;#39;, &amp;#39;after&amp;#39;, &amp;#39;it&amp;#39;, &amp;#39;was&amp;#39;, &amp;#39;hit&amp;#39;]
    # 따라서 word for ~ 의 iterator가 연산 가능하다.

    word = [word for word in re.sub(r&amp;#39;[^\w]&amp;#39;,&amp;#39; &amp;#39;, paragraph).lower().split()
               if word not in banned]
    # 바로 위 리스트에서 banned 의 요소가 제외된다.
    # [&amp;#39;bob&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;ball&amp;#39;, &amp;#39;the&amp;#39;, &amp;#39;ball&amp;#39;, &amp;#39;flew&amp;#39;, &amp;#39;far&amp;#39;, &amp;#39;after&amp;#39;, &amp;#39;it&amp;#39;, &amp;#39;was&amp;#39;]
    
    counts = collections.Counter(words)
    # Counter({&amp;#39;hit&amp;#39;: 3, &amp;#39;ball&amp;#39;: 2, &amp;#39;bob&amp;#39;: 1, &amp;#39;a&amp;#39;: 1, &amp;#39;the&amp;#39;: 1, &amp;#39;flew&amp;#39;: 1, &amp;#39;far&amp;#39;: 1, &amp;#39;after&amp;#39;: 1, &amp;#39;it&amp;#39;: 1, &amp;#39;was&amp;#39;: 1}) 객체를 반환
    return counts.most_common(1)[0][0] # collection.most_common(1)은 [(&amp;#39;hit&amp;#39;, 3)]를 반환)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/북TIL</category>
      <category>문자열조작</category>
      <category>북틸</category>
      <category>상길북</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/74</guid>
      <comments>https://devpanda.tistory.com/74#entry74comment</comments>
      <pubDate>Wed, 27 Jul 2022 19:08:38 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 알고리즘 인터뷰 5장 리스트, 딕셔너리</title>
      <link>https://devpanda.tistory.com/73</link>
      <description>&lt;h3&gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬의 자료형은 모두 객체&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다양한 모듈들, 특히 딕셔너리와 관련된 특수 형태의 컨테이너 자료형들을 활용하자&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;defaultdict&lt;/code&gt;, &lt;code&gt;Counter&lt;/code&gt;, &lt;code&gt;OrderedDict&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;2022.07.20. WED&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬 알고리즘 인터뷰 5장 리스트, 딕셔너리&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬은 모든 것이 객체다.리스트 또한 객체에 대한 포인터목록을 관리하는 형태로 구현되어 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-c' lang='c'&gt;// CPython 에서 리스트는 요소에 대한 포인터목록을 갖고 있는 구조체로 선언되어 있다.
typeof struct {
    PyObject_VAR_HEAD
    PyObject **ob_item;
    // 포인트 목록으로 사이즈를 조절하는 형태로 리스트요소 추가가 구현된다.
    Py_ssize_t allocated;
}  pyListObject;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이로인해 파이썬의 리스트는 배열과 연결 리스트를 합친듯한 강력한 기능을 제공할 수 있다.&lt;em&gt;(그 과정에서 속도는 희생된다)&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파이썬의 딕셔너리는 숫자, 문자, 집합까지 불변 객체를 모두 키로 사용한다. 이 과정을 해싱이라고 하며, 해시 테이블을 이용해 자료를 저장한다. 입력과 조회는 O(1)에 가능하다.&lt;em&gt;(최악의 경우에는 O(n))&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3.7버전부터는  Dict의 입력순서가 유지되나, 3.6이하에서는 &lt;code&gt;collections.OrderedDict()&lt;/code&gt;라는 별도 자료형을 이용해야 유지된다.&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;당연하지만 다양한 내장 모듈들을 이해하고 문제풀이에 적용하는 것이 중요할듯..&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CPython?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파이썬 프로그래밍언어의 참조 구현체. 내부가 C 언어로 구현된 파이썬이며 코드는 &lt;a href='https://github.com/python/cpython'&gt;여기&lt;/a&gt;에서 확인가능.&lt;/li&gt;
&lt;li&gt;이름에서 추측할 수 있듯 CPython 외에도 JVM에서 실행할 수 있는 Jython도 있으며 python으로 구현한 pypy도 있다고한다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/북TIL</category>
      <category>내장모듈</category>
      <category>딕셔너리</category>
      <category>리스트</category>
      <category>파이썬</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/73</guid>
      <comments>https://devpanda.tistory.com/73#entry73comment</comments>
      <pubDate>Wed, 20 Jul 2022 14:55:05 +0900</pubDate>
    </item>
    <item>
      <title>[파이썬] 백준 2798번 블랙잭</title>
      <link>https://devpanda.tistory.com/72</link>
      <description>&lt;h4&gt;백준 2987번 블랙잭&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;브루트포스 문제&lt;/li&gt;

&lt;/ul&gt;
&lt;h5&gt;처음 내 접근 방법은&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;리스트 내 요소를 3개씩 뽑고 새로운 리스트에 담기.&lt;/li&gt;
&lt;li&gt;그 과정에서 목표숫자가 나오면 즉시 return하며 종료&lt;/li&gt;
&lt;li&gt;나오지 않을 경우 새롭게 만들어진 리스트에서 이진탐색으로 값 출력하는 방법으로 풀었었다.&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;코드로하면 아래와 같다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;import sys
# 이진탐색을 위한 bisect
from bisect import bisect_left, bisect_right

cards, goal = map(int, sys.stdin.readline().split())
numbers = list(map(int, sys.stdin.readline().split()))
# 더해진 값들을 담아줄 리스트
sum_list = []

def blackjack(goal, numbers):
    global sum_list
    # 리스트 내 포인터역할
    first = 0
    second = first+1
    third = first+2
    while True:
        # 최소 3개의 조합이 나와야하므로 마지막 3개의 합이 마지막 경우의 수
        # first 포인터가 인덱스 [-3]에 위치하면 마지막 합계 더하고 종료
        if first == len(numbers)-3:
            sum_value = numbers[first] + numbers[second] + numbers[third]
            sum_list.append(sum_value)
            break
        # third 인덱스가 리스트 마지막 값까지 가도록
        if third &amp;lt; len(numbers):
            sum_value = numbers[first] + numbers[second] + numbers[third]
            sum_list.append(sum_value)
            third += 1
        else:
            # third가 길이를 초과할 경우 second 증가
            if second &amp;lt; len(numbers)-1:
                second += 1
                third = second + 1
            else:
                # second도 초과할 경우 first 증가
                first += 1
                second = first+1
                third = first+2
    # 목표값이 sum_list에 있다면 바로 출력
    if goal in sum_list:
        print(goal)
    else:
        # 없을 경우 이진탐색으로 찾아주기
        sum_list = sorted(sum_list)
        try:
            target = bisect_left(sum_list, goal)-1
            left = sum_list[target]
            right = sum_list[target+1]
            print(left if target-left &amp;lt; right-target else right)
        except:
            print(sum_list[-1])


blackjack(goal, numbers)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h5&gt;이 문제 풀려고 이진탐색까지 쓰는 풀이는 나밖에 없지않을까..&lt;/h5&gt;
&lt;h4&gt;보다 효율적인 방법이 있을것같아, 다른 사람의 풀이를 참고했다.&lt;/h4&gt;
&lt;h4&gt;간단하게 3중 for문과 max()를 통해 해결할 수 있었다.&lt;/h4&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;import sys

numbers, N = map(int, sys.stdin.readline().split())
cards = list(map(int, sys.stdin.readline().split()))
length = len(cards)

def blackjack():
    bigger = 0
    for i in range(length-2):
        for j in range(i+1, length-1):
            # 여기서 k 값을 i+2로 시작하게 될 경우, 같은 요소로 더하는 경우가 발생해 실패한다.
            for k in range(j+1, length):
                total = cards[i]+cards[j]+cards[k]
                if total &amp;gt; N:
                    continue
                else:
                    bigger = max(total, bigger)
    print(bigger)


blackjack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;두 풀이 중 위는 메모리: 40300 KB, 시간: 160 ms&lt;/p&gt;
&lt;p&gt;아래는 메모리: 30840 KB, 시간: 120 ms 만큼 소요된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;보기도 좋고 풀이하기도 편하고 성능도 좋다. 위의 풀이를 사용할 이유가 없다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;하노이탑 쌓기 문제에 스택을 사용하려했던 것도 그렇고, 필요 이상의 리스트 사용을 줄여야겠다.&lt;/p&gt;</description>
      <category>개발/알고리즘</category>
      <category>백준</category>
      <category>브루트포스</category>
      <category>블랙잭</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/72</guid>
      <comments>https://devpanda.tistory.com/72#entry72comment</comments>
      <pubDate>Tue, 19 Jul 2022 11:48:39 +0900</pubDate>
    </item>
    <item>
      <title>데이터베이스의 병행제어기법</title>
      <link>https://devpanda.tistory.com/71</link>
      <description>&lt;h3&gt;데이터베이스의 병행제어&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;병행제어란 ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;여러개의 트랜잭션이 동시에 수행될 때 &lt;strong&gt;DB의 일관성&lt;/strong&gt;을 파괴하지 않도록 트랜잭션간의 상호작용을 제어하는 것&lt;/li&gt;
&lt;li&gt;병행(concurrency)는 매우 빠르게 여러 트랜잭션 사이를 이동하면서 조금씩 처리를 수행하는 방식&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;병행 제어의 목적은 일관성 외에도,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DB 공유도 최대화, 시스템 활용도 최대화, 사용자 응답 시간 최소화 등이 있다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;병행 제어를 하지 않을 경우 트랜재션들이 동시에 DB에 접근하며 문제가 생긴다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;병행제어에 실패한다면&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;갱신 분실 &lt;/strong&gt;(Lost Update)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;같은 데이터에 둘 이상의 트랜잭션이 동시에 갱신할 때, 갱신 결과의 일부가 없어지는 것.&lt;/li&gt;
&lt;li&gt;동일한 데이터 X에 값을 더하는 두 트랜잭션이 있을 때, 후행하는 트랜잭션은 &lt;strong&gt;선행 트랜잭션 값이 더해지기 전의 값을 받아오기에&lt;/strong&gt; 두 트랜잭션이 올바르게 반영되지 않는 상황.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;모순성&lt;/strong&gt; (Inconsistency)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하나의 트랜잭션이 여러 데이터 갱신을 수행할 때, 일관성 없는 상태의 DB에서 데이터를 가져와 데이터에 불일치가 발생하는 현상&lt;/li&gt;
&lt;li&gt;갱신 분실과 비슷하지만, 한 트랜잭션이 여러 값을 연산하게 될 경우 &lt;strong&gt;각 값이 참조하는 시기가 모두 달라&lt;/strong&gt; 데이터의 불일치가 발생&lt;/li&gt;
&lt;li&gt;트랜잭션 1이 X, Y 값을  X-&amp;gt;Y 값 순서로 갱신할 때 그 사이에 X, Y값을 갱신하는 또 다른트랜잭션 2가 개입해 트랜잭션 1의 일관성이 깨지는 상황&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;연쇄 복귀&lt;/strong&gt;(Cascading Rollback)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;병행 수행되던 둘 이상의 트랜잭션 중, 하나의 트랜잭션만 실패했지만 두 트랜잭션 모두 복귀되는 현상&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;비완료 의존성&lt;/strong&gt; (Uncommitted Dependency)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하나의 트랜잭션 수행이 실패 후 &lt;strong&gt;회복하기 전에&lt;/strong&gt; 다른 트랜잭션이 실패한 결과를 참조&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;병행제어 기법&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;로킹&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;타임스탬프&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;데이터에 접근하는 시간을 미리 정해 시간 순으로 접근.&lt;/li&gt;
&lt;li&gt;직렬 가능성을 보장하지만, 연쇄 복귀를 초래할 수 있음.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;낙관적 병행제어&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;트랜잭션 종료 시 일괄적으로 검사&lt;/li&gt;
&lt;li&gt;트랜잭션을 위해 유지되는 로컬 사본에 대해서만 갱신&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다중 버전 병행제어&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;여러 버전 값을 유지하며 조회 성능을 최대한 유지하기 위한 방법&lt;/li&gt;
&lt;li&gt;트랜잭션이 충돌할 경우 대기가 아니라 롤백함으로써 연쇄복귀초래 가능성O&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;로킹(Locking)&lt;/h3&gt;
&lt;h4&gt;로킹이란?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;병행 수행되는 트랜잭션들이 동일한 데이터에 동시에 접근하지 못하게 하여 직렬 가능성을 보장한다.&lt;/li&gt;
&lt;li&gt;lock, unlock 연산을 이용해 제어&lt;/li&gt;
&lt;li&gt;로킹되는 단위가 커지면 트랜잭션 데이터 단위(로크)가 커져 수가 줄어들고 제어기법이 간단해져 병행성이 감소&lt;/li&gt;
&lt;li&gt;반대로 로킹 단위가 작아져 병행성이 증가하지만 제어기법이 까다로워진다.&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;직렬 가능성 ? 트랜잭션들이 병행 수행되더라도 순차적으로 수행된 것과 동일한 DB 일관성을 보장하는 것&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;데드락 ?  2개 이상의 트랜잭션이 서로 상대방이 보유하고 있는 로크를 요청하면서 기다리고 있는 상태 &lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>개발</category>
      <category>데드락</category>
      <category>데이터베이스</category>
      <category>로킹</category>
      <category>병행제어</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/71</guid>
      <comments>https://devpanda.tistory.com/71#entry71comment</comments>
      <pubDate>Sat, 16 Jul 2022 12:05:49 +0900</pubDate>
    </item>
    <item>
      <title>인터페이스 모듈 연계 방식 EAI와 ESB</title>
      <link>https://devpanda.tistory.com/70</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;시스템 통합의 문제&lt;/h2&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;이렇게 나눠진 시스템 사이에는 통신이 필요했고, 시스템이 커지면서 시스템간 P2P로 직접 통신하는 구조는 한계에 이르렀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해 등장한 솔루션이 EAI, ESB다.&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;502&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCgIUd/btrUSAyMhod/tFChUqVdKGr2Ki1q2Lc5Mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCgIUd/btrUSAyMhod/tFChUqVdKGr2Ki1q2Lc5Mk/img.png&quot; data-alt=&quot;시스템간 통신, 통합&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCgIUd/btrUSAyMhod/tFChUqVdKGr2Ki1q2Lc5Mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCgIUd%2FbtrUSAyMhod%2FtFChUqVdKGr2Ki1q2Lc5Mk%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;265&quot; height=&quot;149&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시스템간 통신, 통합&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 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;b&gt;모듈 간 데이터 교환을 위해 관계를 설정&lt;/b&gt;하는 것&lt;/li&gt;
&lt;li&gt;시스템에서 인터페이스를 위해 외부 및 내부 모듈을 연계하는 대표적 방법에는 EAI, ESB방식이 있다.&lt;/li&gt;
&lt;li&gt;두 방식의 큰 차이는 구성 방식이 &lt;b&gt;중앙집중형 vs 버스형태&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;EAI 방식&lt;/h2&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;706&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SnoGi/btrURlWsFae/hLn2trKFYpOfQRHMkfXj8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SnoGi/btrURlWsFae/hLn2trKFYpOfQRHMkfXj8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SnoGi/btrURlWsFae/hLn2trKFYpOfQRHMkfXj8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSnoGi%2FbtrURlWsFae%2FhLn2trKFYpOfQRHMkfXj8K%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;361&quot; height=&quot;143&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중앙의 EAI가 허브역할을 하면서, 모든 통신이 EAI를 거친다. 이 EAI에는 &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;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ESB 방식&lt;/h2&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;700&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfz4Tt/btrUVcc9TlV/4qTDx2Mht5hAZ0kf9ohGIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfz4Tt/btrUVcc9TlV/4qTDx2Mht5hAZ0kf9ohGIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfz4Tt/btrUVcc9TlV/4qTDx2Mht5hAZ0kf9ohGIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbfz4Tt%2FbtrUVcc9TlV%2F4qTDx2Mht5hAZ0kf9ohGIk%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;355&quot; height=&quot;134&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이기종간 통합이 많아지고 시스템이 분리되다보니 이를 표준화하려했고, 이것이 SOA(서비스 지향 아키텍쳐)이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;통신이 표준화됐기에, 별도의 어댑터들이 필요 없어졌고, 대신 서비스 버스라는 통신 백본을 이용해 통신&lt;/b&gt;을 하는 ESB가 등장했다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #666666;&quot;&gt;백본(backbone) 또는 백본망(backbone network, 문화어: 중추망)은&amp;nbsp;다양한 네트워크를 상호 연결하는 컴퓨터 네트워크의 일부로서, 각기 다른 LAN이나 부분망 간에 정보를 교환하기 위한 경로를 제공한다.&lt;/span&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;/li&gt;
&lt;li&gt;EAI + SOA &lt;i&gt;(서비스지향아키텍쳐)&amp;nbsp;&lt;/i&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;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;참고 - &lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://bcho.tistory.com/1292&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bcho.tistory.com/1292 조대협님 블로그&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발</category>
      <category>cs</category>
      <category>모듈</category>
      <category>연계</category>
      <category>인터페이스</category>
      <category>정보처리기사</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/70</guid>
      <comments>https://devpanda.tistory.com/70#entry70comment</comments>
      <pubDate>Thu, 14 Jul 2022 20:37:30 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 파이썬 알고리즘 인터뷰 1~3장</title>
      <link>https://devpanda.tistory.com/69</link>
      <description>&lt;h3 &gt;&lt;strong&gt;오늘 TIL 3줄 요약&lt;/strong&gt;&lt;/h3&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;strong&gt;공백 4칸&lt;/strong&gt;(PEP 8)&lt;/li&gt;
&lt;li&gt;좋은 코드는 얼핏 쳐다 보기만해도 향기가 난다.&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 &gt;&lt;strong&gt;TIL (Today I Learned) 날짜&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;2022.07.14 THU&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt; &lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 범위&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파이썬알고리즘인터뷰(상길북)1~3장&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;책에서 기억하고 싶은 내용을 써보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;파이썬은 동적 타이핑 언어로 사용하기엔 매우 편하지만, 타입을 명시하지 않으면 가독성을 낮추고 버그 발생 확률이 높아진다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;# 타입을 명시하는 예
from typing import TypeVar

# 파이썬의 typing 내장 패키지가 파이썬을 정적 타입으로 만들어주지는 않는다.
# 그러나 코드 상에 타입을 명시할 수 있고, 에디터 레벨에서 경고를 띄워주는것이 가능.

T = TypeVar(&amp;#39;T&amp;#39;)
U = TypeVar(&amp;#39;U&amp;#39;)

def are_equal(a:T, b:U) -&amp;gt; bool:
    return a == b

are_equal(10, 10.0)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파이썬에는 구조체가 없어 네임드튜플을 사용하거나 dataclass 데코레이션(3.7이후)을 사용해 구조체 형태로 정의할 수 있다&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-python' lang='python'&gt;# python 3.7+
from dataclasses import dataclass

@dataclass
# 클래스를 구현할때 데이터 클래스를 선언해주면 여러 내부 함수의 기능도 자동으로 구현가능
class Product:
    weight: int = None
    price: float = None
    # 타입 힌트와 함께 사용
        
apple = Product()
apple.price = 10
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;가독성을 위해 람다, 리스트 컴프리헨션 등 표현식은 2개를 넘지 않아야 한다.&lt;/li&gt;
&lt;li&gt;제너레이터는 루프의 반복 동작(iteration)을 제어할 수 있는 루틴 형태.&lt;/li&gt;
&lt;li&gt;제너레이터를 쓸 때 yield 구문을 사용하면 return과 달리 실행 중이던 값을 내보내고, 함수의 끝까지 실행된다.&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;람다표현식에 map이나 filter를 사용하는 것이 더 능숙해보이고 어려워보였는데, &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;정작 리스트 컴프리헨션을 이용하는게 가독성이 높다는 점이 인상적이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;   &lt;br/&gt;  &lt;br/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;제네릭 프로그래밍&lt;/strong&gt;(&lt;a href='https://ko.wikipedia.org/wiki/영어'&gt;영어&lt;/a&gt;: generic programming)은 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 &lt;a href='https://ko.wikipedia.org/wiki/프로그래밍'&gt;프로그래밍&lt;/a&gt; 방식이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;즉 클래스를 정의 할 때는 데이터 타입을 확정하지 않고 인스턴스를 생성할 때 데이터 타입을 지정하는 기능이 제네릭이다. 이를 통해 중복의 제거와 타입 안정성의 추구가 가능해진다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;또한 자바와 같은 컴파일 언어의 경우 실행중 런타임 에러를 맞는것보다, 컴파일 단계에서 에러를 내는것이 안전한데, 제네릭의 사용은 이를 가능하게 해준다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;</description>
      <category>개발/북TIL</category>
      <category>구조체</category>
      <category>동적타이핑</category>
      <category>알고리즘</category>
      <category>제네릭</category>
      <category>파이썬</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/69</guid>
      <comments>https://devpanda.tistory.com/69#entry69comment</comments>
      <pubDate>Thu, 14 Jul 2022 19:51:56 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트의 비동기 처리</title>
      <link>https://devpanda.tistory.com/68</link>
      <description>&lt;h2 &gt;&amp;gt; 비동기처리란&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;특정 코드 연산이 끝날 때까지 기다리는 것이 아니라, 멈추지 않고 다음 코드를 실행하는 특성&lt;/li&gt;
&lt;li&gt;서버에서 응답을 언제 줄 지 모르기 때문에 다양한 요청을 비동기로 처리&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 &gt; &lt;/h1&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 &gt;&amp;gt; 문제점&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;비동기 처리 방식은 효율적이지만 때로 문제를 일으킴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API에서 응답을 받고 처리해준다던지 &lt;/li&gt;
&lt;li&gt;페이지가 완전히 로드되기 전에 응답을 받아와 빈 값을 리턴하는 경우가 있었음  &lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 &gt; &lt;/h1&gt;
&lt;h2 &gt;&amp;gt; 해결방법 &lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;콜백함수 사용&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;그러나 콜백함수는 중첩될 경우 가독성이 떨어지고 로직 변경도 어려움&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class='language-javascript' lang='javascript'&gt;/// 예시
$.get(&amp;#39;url&amp;#39;, function(response)) {
      parseValue(response, function(id) {
    	auth(id, function(result) {
            display(result, function(text) {
                console.log(text)\;
            });
        });
	});
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Promise 사용&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Async 사용  &lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;blockquote&gt;&lt;h4 &gt;위 콜백 중첩을 분리하더라도 2, 3번 방법이 낫다.  &lt;/h4&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 &gt; &lt;/h1&gt;
&lt;h2 &gt;&amp;gt; Promise란?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Promise&lt;/code&gt;&lt;/strong&gt; 객체는 비동기 작업이 맞이할 미래의 결과 값의 대리자&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;동기 메서드처럼 값을 반환&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;최종 결과를 반환하는 것은 아님&lt;/li&gt;
&lt;li&gt;이행 또는 거부됐을 경우 setteld(처리)되었다고 표현  &lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 &gt; &lt;/h1&gt;
&lt;h3 &gt;&amp;gt; Promise의 3가지 상태&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Pending&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new Promise(function(resolve, reject){});&lt;/code&gt; 메서드를 호출한 상태&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fulfilled&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;펜딩 상태에서 콜백함수의 resolve를 실행하게 되면 이행 상태가 된다.&lt;/li&gt;
&lt;li&gt;이때 &lt;code&gt;getSomething().then(function(){});&lt;/code&gt;과 같이 then()을 이용해 값을 받을 수 있게 된다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rejected&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;reject&lt;/code&gt;를 받게 되면 실패 상태가 되며 &lt;code&gt;getSomething().then().catch(function(err){});&lt;/code&gt; 에러를 인자로 받을 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;catch()&lt;/code&gt;가 아닌 &lt;code&gt;then()&lt;/code&gt;의 두번째 인자로 에러를 처리해도 되지만 &lt;em&gt;에러를 못잡는 경우와 가독성을 위해&lt;/em&gt;  가급적 &lt;strong&gt;&lt;code&gt;catch()&lt;/code&gt;&lt;/strong&gt;로 처리해주자.  &lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h1 &gt; &lt;/h1&gt;
&lt;h4 &gt; &lt;/h4&gt;
&lt;h4 &gt; &lt;/h4&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;참고- mdn, 캡틴판교님 블로그&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <category>비동기</category>
      <category>자바스크립트</category>
      <category>콜백</category>
      <category>프로미스</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/68</guid>
      <comments>https://devpanda.tistory.com/68#entry68comment</comments>
      <pubDate>Tue, 12 Jul 2022 22:36:24 +0900</pubDate>
    </item>
    <item>
      <title>절치부심</title>
      <link>https://devpanda.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;I'd started work out at 22. Back then, I couldn't realize the importance of STEADINESS. I worked out 3 or 4 times a week, but I wasn't consistent. I didn't make my body great with these effort.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;As time passed, my body gradually improved as I exercised steadily and managed my diet, &lt;b&gt;whether I liked it or not.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;This experience taught me a lesson about the importance of persistence.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;Focusing on distant future makes me discouraged. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;Keep concentrating daily routine and sticking to execute that makes me to go forward.&lt;/span&gt;&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;2 failures and fear. I must get over those shit through small progress&lt;/p&gt;</description>
      <category>일상/생각대로</category>
      <category>haruki</category>
      <category>steadiness</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/67</guid>
      <comments>https://devpanda.tistory.com/67#entry67comment</comments>
      <pubDate>Fri, 17 Jun 2022 10:13:41 +0900</pubDate>
    </item>
    <item>
      <title>2022. 05. 24.</title>
      <link>https://devpanda.tistory.com/66</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;I recently got a rash on my arm. I also have itching. At first I thought it was a little annoying. As I got more and more itchy and had another rash on the other side, it made me worry. So I went to the dermatologist and he said it was like a sun allergy. It won't be anything like he said, but it hasn't improved, so I'm a little afraid of it.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;When I started to worry about my health like hypochondriac, I am very thankful that I am healthy. Isn't it funny.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;I want to be a person who can always be thankful. Not only under the particualr situation.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/66</guid>
      <comments>https://devpanda.tistory.com/66#entry66comment</comments>
      <pubDate>Tue, 24 May 2022 19:04:05 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 실용주의 프로그래머 4. 실용주의 편집증</title>
      <link>https://devpanda.tistory.com/65</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘 TIL 3줄 요약&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;믿지마라. 자신도! 1분은 60초가 아닐 수 있고, 1달은 28일보다 작을 수 있다. 확실한 것은 없다.&lt;/li&gt;
&lt;li&gt;작게 쪼개서 일해나가라.&lt;/li&gt;
&lt;li&gt;먼 미래를 예상하지 말고 당장의 프로그램을 DRY와 같은 원칙을 지켜 만들어나가라.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TIL (Today I Learned) 날짜&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;&amp;nbsp;2022. 05. 19. THU&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;4장&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;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;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;스코프와 리소스에서 작가는 또 같은 얘기를 하고 있다. 큰 주제는 결합도가 낮아지도록 신경써서 작성하고 다듬으라. 앞서 읽었던 엔트로피와 잔디밭 이야기처럼 꾸준한 관리와 신경이 읽기 편하고 유지보수하기 쉬운 코드를 만드나보다.&amp;nbsp;&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;&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;dbc가 언어로 구현된 경우는 타입스크립트 같이 데이터 타입을 정확하게 명시하는 경우를 뜻하는 것인가?&lt;/p&gt;</description>
      <category>개발/북TIL</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/65</guid>
      <comments>https://devpanda.tistory.com/65#entry65comment</comments>
      <pubDate>Fri, 20 May 2022 00:31:35 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 실용주의 프로그래머 3. 기본도구</title>
      <link>https://devpanda.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘 TIL 3줄 요약&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;모든 것을 CVS 아래에 두고 개발 환경 마저도 쉽게 옮길수 있게 만들라.&lt;/li&gt;
&lt;li&gt;디버깅을 두려워 하지마라.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TIL (Today I Learned) 날짜&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;&amp;nbsp;2022. 05. 18. WED&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3장&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작업하는 것이 소스 코드가 아닐지라도, 모든 것을 버전관리 아래에 둬라. 각종 문서, 전화번호 목록, 외부 업체에 보내는 메모, makefile, 빌드와 릴리스 절차, 로그 파일을 정리하는 작은 셸 스크립트까지 모두 다.&amp;nbsp;&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;/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;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;이번 장에서는 꽤 친숙한 내용들이 많았다. CLI에 친숙해져야 한다는 것이나 VSC의 다양한 기능 등 작가가 말하고자 하는 바를 어디선가(어쩌면 노마드코더에서?) 접해본 내용들이었다.&amp;nbsp;&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;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;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; -&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴퓨팅에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;텍스트 처리&lt;/b&gt;(text processing) 또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;문자 처리&lt;/b&gt;는 전자 텍스트의 생성 또는 조작을 자동화하는 이론과 실천을 의미한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;텍스트&lt;/b&gt;(text)는 해당 실천에 관여하는 사람의 키보드를 통해 지정된 영숫자 전체를 의미하는 것이 보통이지만 일반적으로 텍스트는 대상 텍스트의 표준&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%AC%B8%EC%9E%90_%EC%9D%B8%EC%BD%94%EB%94%A9&quot;&gt;문자 인코딩&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;바로 위의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%B6%94%EC%83%81%ED%99%94_%EA%B3%84%EC%B8%B5&quot;&gt;추상화 계층&lt;/a&gt;을 의미한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;처리&lt;/b&gt;라는 용어는 자동화된(기계화된) 처리를 의미하며 이는 수동으로 수행되는 동일 조작과는 대조적이다.&lt;/p&gt;</description>
      <category>개발/북TIL</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/64</guid>
      <comments>https://devpanda.tistory.com/64#entry64comment</comments>
      <pubDate>Wed, 18 May 2022 21:20:46 +0900</pubDate>
    </item>
    <item>
      <title>null undefined의 차이</title>
      <link>https://devpanda.tistory.com/63</link>
      <description>&lt;h1 &gt;Null 과 Undefined 차이&lt;/h1&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-javascript' lang='javascript'&gt;// 정의되지 않고 초기화된 적도 없는 foo
foo; //ReferenceError: foo is not defined

// 존재하지만 값이나 자료형이 존재하지 않는 foo
var foo = null;
foo; //null

// null은 어떤 값이 의도적으로 비어있음을 표현
typeof null === &amp;#39;object&amp;#39; // true

var x; // 값을 할당하지 않고 변수 선언
console.log(&amp;quot;x&amp;#39;s value is&amp;quot;, x) // &amp;quot;x&amp;#39;s value is undefined&amp;quot; 출력

// undefined는 선언한 후 값을 할당하지 않은 변수 혹은 주어지지 않은 인수에 자동 할당.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;null, undefined 모두 원시값에 해당한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;원시값이란 객체가 아니면서 메서드도 가지지 않는 데이터이다.&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;원시 값은 변형할 수 없다. (원시 값에 새로운 값을 부여-할당-할 수는 있다.)&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <category>자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/63</guid>
      <comments>https://devpanda.tistory.com/63#entry63comment</comments>
      <pubDate>Mon, 16 May 2022 17:20:04 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 실용주의 프로그래머 2장</title>
      <link>https://devpanda.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘 TIL 3줄 요약&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;ETC) 내가 방금 한 일이 전체 시스템을 바꾸기 쉽게 만들었을까 어렵게 만들었을까?&lt;/li&gt;
&lt;li&gt;코드중복과&lt;span&gt; &lt;/span&gt;지식중복은&lt;span&gt; &lt;/span&gt;구분되어야&lt;span&gt; &lt;/span&gt;한다&lt;span&gt;. (후자는 허용)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;DRY) 코드의 중복: 의도나 기능을 수정할 때 여러 라인의 같은 코드들을 수정해야하지 않을까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TIL (Today I Learned) 날짜&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;&amp;nbsp;2022. 05. 15. SUN&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2장&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리가 소프트웨어를 개발하는 속도는 요구사항, 사용자, 하드웨어의 변화를 앞지를 수 없다.&lt;/li&gt;
&lt;li&gt;그렇기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;직교성&lt;span&gt;, &lt;/span&gt;결합도&lt;span&gt; &lt;/span&gt;등을&lt;span&gt; &lt;/span&gt;고려해&lt;span&gt; &lt;/span&gt;유지보수하기&lt;span&gt; &lt;/span&gt;쉽게&lt;span&gt; &lt;/span&gt;만들어야한다&lt;span&gt;.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;거대&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;공학적&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;접근&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;방식&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;각각의&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;모듈&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;작성&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;결합&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;과&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;반대되는&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;예광탄&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;코드를&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;활용하라&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;li&gt;헬리콥터를 조종하는 것처럼 한 가지 기능을 수정하기 위해 4~5개 이상의 모듈을 수정하고 있다면 이는 무언가 잘못된 것이다..!&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;</description>
      <category>개발/북TIL</category>
      <category>노개북</category>
      <category>노마드코더</category>
      <category>챌린지</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/62</guid>
      <comments>https://devpanda.tistory.com/62#entry62comment</comments>
      <pubDate>Sun, 15 May 2022 19:16:20 +0900</pubDate>
    </item>
    <item>
      <title>[북TIL] 실용주의 프로그래머 1장</title>
      <link>https://devpanda.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘 TIL 3줄 요약&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;자기의 기예(craft)에 관심을 가져라&lt;/li&gt;
&lt;li&gt;훌륭한 잔디밭은 매일 조금씩 손질해주어야 한다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;소프트웨어의 엔트로피, 깨진 창문을 내버려 두지 말라.&lt;/li&gt;
&lt;li&gt;시작 피로를 깨기 위해서는 일단 &amp;lsquo;돌멩이&amp;rsquo;를 내놔라.(돌멩이 수프 이야기)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TIL (Today I Learned) 날짜&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;&amp;nbsp;2022. 05. 15. SUN&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;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;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;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;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;li&gt;일단 완성하고 보자~ 라는 생각은 일을 시작할 땐 도움이 되지만, 중간중간 코드들을 정리하지 않는다면 프로젝트 결과물의 품질과 가독성은 매우 떨어질 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/북TIL</category>
      <category>노개북</category>
      <category>노마드코더</category>
      <category>챌린지</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/61</guid>
      <comments>https://devpanda.tistory.com/61#entry61comment</comments>
      <pubDate>Sun, 15 May 2022 19:10:13 +0900</pubDate>
    </item>
    <item>
      <title>AWS 배포 중 이미지, 비디오 리소스를 받아오지 못하는 경우</title>
      <link>https://devpanda.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;개발환경에서 컴퓨터를 이용한 서버에서는 crossorigin 미들웨어를 사용했다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1649924347271&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;app.use((req, res, next) =&amp;gt; {
  res.header(&quot;Cross-Origin-Embedder-Policy&quot;, &quot;require-corp&quot;);
  res.header(&quot;Cross-Origin-Opener-Policy&quot;, &quot;same-origin&quot;);
  next();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;그러나 AWS로 배포해보니 이미지 소스나 영상 소스를 가져오지 못하고&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1649924539240&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;혹은&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1649924552157&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;AccessControlListNotSupported: The bucket does not allow ACLs&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;등 다양하게 ACL, crossorigin과 관련된 에러를 뱉어낸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;에러에서도 알 수 있듯이 Crossorigin이 문제였던듯하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;i&gt;교차 출처 리소스 공유&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;(Cross-origin resource sharing, CORS),&amp;nbsp;&lt;/span&gt;교차 출처 자원 공유&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;는&amp;nbsp;&lt;/span&gt;웹 페이지&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;&amp;nbsp;상의 제한된&amp;nbsp;&lt;/span&gt;리소스&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;를 최초 자원이 서비스된 도메인 밖의 다른&amp;nbsp;&lt;/span&gt;도메인&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;으로부터 요청할 수 있게 허용하는 구조이다.&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;원인을 알았으니 해결해보려면 AWS&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;버킷에 &lt;b&gt;ACL권한을 변경해주면 된다.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;권한 -&amp;gt; 객체 소유권 편집 -&amp;gt; ACL 비활성화됨(권장)을 ACL 활성화됨로 변경 -&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;ACL이 복원된다는 것을 확인합니다. 체크 -&amp;gt; 버킷 소유자 선호 체크 -&amp;gt; 변경사항 저장&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;위의 방법까지 해보시고, 그래도 안 되시는 분들은 ACL(액세스 제어 목록)에서 편집-&amp;gt;모든 사람(퍼블릭 액세스)에 나열, 읽기 체크해주신 후 변경사항 저장&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1649929298790&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;No 'Access-Control-Allow-Origin' header is present on the requested resource. net::ERR_FAILED 200&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;위와 같은 오류가 콘솔창에 뜨면 권한 -&amp;gt; CORS(Cross-origin 리소스 공유) 편집 -&amp;gt; 아래 코드를 추가해주시고 변경사항 저장하시면 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/17533888/s3-access-control-allow-origin-header&quot;&gt;https://stackoverflow.com/questions/17533888/s3-access-control-allow-origin-header&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1649929329165&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[
{
&quot;AllowedHeaders&quot;: [
&quot;*&quot;
],
&quot;AllowedMethods&quot;: [
&quot;GET&quot;,
&quot;HEAD&quot;
],
&quot;AllowedOrigins&quot;: [
&quot;*&quot;
],
&quot;ExposeHeaders&quot;: [],
&quot;MaxAgeSeconds&quot;: 3000
}
]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;+ 추가적으로 이미지 태그와 비디오 태그에 crossorigin속성을 추가한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;img(src=`이미지 주소` crossorigin)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;video(src=`비디오 주소` crossorigin)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;CORS 구성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/ManageCorsUsing.html&quot;&gt;https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/ManageCorsUsing.html&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;AllowedOrigins을 설정하는 이유&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;허용하지 않은 origin에서 리소스에 접근 및 사용을 막기 위해서이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;다시 말해, 허용하지 않은 클라이언트에게 리소스를 주지 않기 위함이고, 허용할 대상에 대한 설정이 AllowedOrigins이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #9d9d9d;&quot;&gt;출처) 노마드코더 sugar님, yoon1139님.&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/60</guid>
      <comments>https://devpanda.tistory.com/60#entry60comment</comments>
      <pubDate>Thu, 14 Apr 2022 18:43:29 +0900</pubDate>
    </item>
    <item>
      <title>TailwindCSS</title>
      <link>https://devpanda.tistory.com/58</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;200&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctN5lI/btrxt1leKcW/aKZMqRLU3IJwI01KdQJ4o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctN5lI/btrxt1leKcW/aKZMqRLU3IJwI01KdQJ4o1/img.png&quot; data-alt=&quot;https://tailwindcss.com/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctN5lI/btrxt1leKcW/aKZMqRLU3IJwI01KdQJ4o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctN5lI%2Fbtrxt1leKcW%2FaKZMqRLU3IJwI01KdQJ4o1%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;200&quot; height=&quot;200&quot; data-origin-width=&quot;200&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://tailwindcss.com/&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-03-26 at 8.36.50 PM.png&quot; data-origin-width=&quot;3360&quot; data-origin-height=&quot;2100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cliC6K/btrxhRkJjO9/sPTmbk0ZvYwKRON7u5C4Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cliC6K/btrxhRkJjO9/sPTmbk0ZvYwKRON7u5C4Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cliC6K/btrxhRkJjO9/sPTmbk0ZvYwKRON7u5C4Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcliC6K%2FbtrxhRkJjO9%2FsPTmbk0ZvYwKRON7u5C4Hk%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;3360&quot; height=&quot;2100&quot; data-filename=&quot;Screen Shot 2022-03-26 at 8.36.50 PM.png&quot; data-origin-width=&quot;3360&quot; data-origin-height=&quot;2100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>일상/생각대로</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/58</guid>
      <comments>https://devpanda.tistory.com/58#entry58comment</comments>
      <pubDate>Sun, 27 Mar 2022 09:05:44 +0900</pubDate>
    </item>
    <item>
      <title>[NextJS] Fast refresh가 작동하지 않을 때 (React 18)</title>
      <link>https://devpanda.tistory.com/57</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;React 18이 정식으로 릴리즈되어서 &lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 버전을 최신으로 업데이트하면 Hot reloading이 잘 작동합니다!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NextJS는 Fast refresh를 기본 기능으로 제공한다. (&lt;a href=&quot;https://nextjs.org/docs/basic-features/fast-refresh&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://nextjs.org/docs/basic-features/fast-refresh&lt;/a&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;스타일 등의 컴포넌트를 변경할 때 빠른 리프레시는 매우 편리합니다. 현재 페이지에만 앱을 로드합니다. 대부분의 편집은 1~2초 이내에 표시됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;핫 새로고침은 앱을 실행 상태로 유지하고 런타임에 편집한 파일의 새 버전을 주입하는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;Fast Refresh의 경우 React 컴포넌트만 내보내는 모듈을 편집하면 Fast Refresh는 해당 모듈의 코드만 업데이트하고 컴포넌트를 다시 렌더링합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;React 컴포넌트가 아닌 내보내기 모듈을 편집하면 Fast Refresh는 해당 모듈과 해당 모듈을 Import하는 다른 모듈 모두를 다시 실행합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;React 트리 이외의 모듈에 의해 Import된 파일을 편집하면 Fast Refresh는 완전한 새로고침으로 돌아갑니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;즉, 핫 새로고침보다 더 크고 많은 기능을 제공. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #666666;&quot;&gt;(&lt;a href=&quot;https://stackoverflow.com/questions/59085281/difference-between-hot-reload-and-fast-refresh-in-react-native&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/59085281/difference-between-hot-reload-and-fast-refresh-in-react-native&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 얘기하면 CSS스타일링 등 컴포넌트를 변경할때 nodeJS의 nodemon처럼 페이지 새로고침 없이 코드 변경을 re-render해줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요한건,&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;당근마켓 클론코딩을 하면서 리액트18의 rc버전을 사용했는데, 이런 패스트 리프레시(핫리로드)가 작동하지 않는 것이었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글에 hot reload not working, fast refresh not working을 검색해봐도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트, 모듈의 철자(case) 오타가 원인인 케이스만 검색됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 내 경우는 import export 되는 컴포넌트 명에는 오탈자가 없었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노마드코더 강의 댓글에서 찾은 해결책은 &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;버전 문제&lt;/b&gt;&lt;/span&gt;였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무슨 문제에선지&lt;/p&gt;
&lt;pre id=&quot;code_1648293999656&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &quot;next&quot;: &quot;^12.1.1&quot;,
    &quot;react&quot;: &quot;^18.0.0-rc.3&quot;,
    &quot;react-dom&quot;: &quot;^18.0.0-rc.3&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;위 버전에서는 패스트 리프레시가 작동하지 않는다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1648294033152&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &quot;next&quot;: &quot;^12.0.7&quot;,
    &quot;react&quot;: &quot;^18.0.0-rc.0&quot;,
    &quot;react-dom&quot;: &quot;^18.0.0-rc.0&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;넥스트와 리액트 rc버전 모두를 위와 같이 downgrade하고 나서야 정상작동 됨을 확인했다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;넥스트JS가 제공하는 패스트 리프레시가 작동하지 않는 분들은&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 컴포넌트의 오탈자(특히 대소문자) 확인&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 넥스트와 리액트의 버전 확인을 해보면 좋을듯하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/57</guid>
      <comments>https://devpanda.tistory.com/57#entry57comment</comments>
      <pubDate>Sat, 26 Mar 2022 20:28:45 +0900</pubDate>
    </item>
    <item>
      <title>[NextJS] getSererSideProps</title>
      <link>https://devpanda.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;넥스트JS의 가장 큰 장점인 SSR을 살리기 위해서는 getServerSideProps를 export해주어야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1648003692451&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Home({ results }) {
  // 데이터 렌더링!
}


export async function getServerSideProps() {
  const { results } = await (
    await fetch(&quot;http://localhost:3000/api/movies&quot;)
  ).json();
  return {
    props: {
      results,
    },
  };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 넥스트js는 반환된 데이터를 사용해 req에서 페이지를 pre-render하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요 getServerSideProps는 서버측에서만 실행되며 클라이언트에서는 X&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에게 api에서 fetch하는 동안 듬성듬성한 페이지, 혹은 로딩 페이지를 보여주지 않는 장점 O&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;그러나 SEO와 관련 없는 페이지거나, 데이터 업데이트가 잦은 페이지라면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트에서 렌더링 하는것도 고려해야한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;a href=&quot;https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props&quot;&gt;https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;노마드코더 슈가님(&lt;a href=&quot;https://github.com/GitHubGW&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/GitHubGW&lt;/a&gt;)&lt;/p&gt;
&lt;figure id=&quot;og_1648003943473&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Data Fetching: getServerSideProps | Next.js&quot; data-og-description=&quot;Fetch data on each request with &amp;#96;getServerSideProps&amp;#96;.&quot; data-og-host=&quot;nextjs.org&quot; data-og-source-url=&quot;https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props&quot; data-og-url=&quot;https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BLVSJ/hyNNhyTNbB/X2nSyGPsHw9aIeMVXKAOp1/img.png?width=2048&amp;amp;height=1170&amp;amp;face=0_0_2048_1170&quot;&gt;&lt;a href=&quot;https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BLVSJ/hyNNhyTNbB/X2nSyGPsHw9aIeMVXKAOp1/img.png?width=2048&amp;amp;height=1170&amp;amp;face=0_0_2048_1170');&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;Data Fetching: getServerSideProps | Next.js&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Fetch data on each request with `getServerSideProps`.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nextjs.org&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>개발/자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/56</guid>
      <comments>https://devpanda.tistory.com/56#entry56comment</comments>
      <pubDate>Thu, 24 Mar 2022 12:53:08 +0900</pubDate>
    </item>
    <item>
      <title>진주 하대동 라무진</title>
      <link>https://devpanda.tistory.com/55</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;한줄요약 - 가격값하는 맛집. 비싼만큼 맛있고 신선한 양갈비&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여자친구 임용고시 합격기념으로 다녀왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;맥주랑 하이볼 곁들였고,&lt;b&gt; 1인당 5만원&lt;/b&gt; 이상 나온듯!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe mapdata=&quot;addr=%EA%B2%BD%EB%82%A8%20%EC%A7%84%EC%A3%BC%EC%8B%9C%20%ED%95%98%EB%8C%80%EB%8F%99%20348-6&amp;amp;addtype=1&amp;amp;confirmid=854027579&amp;amp;docid=&amp;amp;idx=1&amp;amp;ifrH=362px&amp;amp;ifrW=490px&amp;amp;mapHeight=362&amp;amp;mapInfo=%7B%22version%22%3A2%2C%22mapWidth%22%3A490%2C%22mapHeight%22%3A362%2C%22mapCenterX%22%3A755365%2C%22mapCenterY%22%3A471723%2C%22mapLevel%22%3A4%2C%22coordinate%22%3A%22wcongnamul%22%2C%22markInfo%22%3A%5B%7B%22markerType%22%3A%22standPlace%22%2C%22coordinate%22%3A%22wcongnamul%22%2C%22x%22%3A755366%2C%22y%22%3A471729%2C%22clickable%22%3Atrue%2C%22draggable%22%3Atrue%2C%22icon%22%3A%7B%22width%22%3A35%2C%22height%22%3A56%2C%22offsetX%22%3A17%2C%22offsetY%22%3A56%2C%22src%22%3A%22%2F%2Ft1.daumcdn.net%2Flocalimg%2Flocalimages%2F07%2F2012%2Fattach%2Fpc_img%2Fico_marker2_150331.png%22%7D%2C%22content%22%3A%22%EB%9D%BC%EB%AC%B4%EC%A7%84%22%2C%22confirmid%22%3A854027579%7D%5D%2C%22graphicInfo%22%3A%5B%5D%2C%22roadviewInfo%22%3A%5B%5D%7D&amp;amp;mapWidth=490&amp;amp;mapX=755365&amp;amp;mapY=471723&amp;amp;map_hybrid=false&amp;amp;map_level=4&amp;amp;map_type=TYPE_MAP&amp;amp;rcode=4817067800&amp;amp;tel=055-762-0951&amp;amp;title=%EB%9D%BC%EB%AC%B4%EC%A7%84&quot; src=&quot;/proxy/plusmapViewer.php?id=maps_1644924066257&quot; id=&quot;maps_1644924066257&quot; width=&quot;540px&quot; height=&quot;350px&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; data-ke-type=&quot;map&quot; data-maps-data=&quot;addr=%EA%B2%BD%EB%82%A8%20%EC%A7%84%EC%A3%BC%EC%8B%9C%20%ED%95%98%EB%8C%80%EB%8F%99%20348-6&amp;amp;addtype=1&amp;amp;confirmid=854027579&amp;amp;docid=&amp;amp;idx=1&amp;amp;ifrH=362px&amp;amp;ifrW=490px&amp;amp;mapHeight=362&amp;amp;mapInfo=%7B%22version%22%3A2%2C%22mapWidth%22%3A490%2C%22mapHeight%22%3A362%2C%22mapCenterX%22%3A755365%2C%22mapCenterY%22%3A471723%2C%22mapLevel%22%3A4%2C%22coordinate%22%3A%22wcongnamul%22%2C%22markInfo%22%3A%5B%7B%22markerType%22%3A%22standPlace%22%2C%22coordinate%22%3A%22wcongnamul%22%2C%22x%22%3A755366%2C%22y%22%3A471729%2C%22clickable%22%3Atrue%2C%22draggable%22%3Atrue%2C%22icon%22%3A%7B%22width%22%3A35%2C%22height%22%3A56%2C%22offsetX%22%3A17%2C%22offsetY%22%3A56%2C%22src%22%3A%22%2F%2Ft1.daumcdn.net%2Flocalimg%2Flocalimages%2F07%2F2012%2Fattach%2Fpc_img%2Fico_marker2_150331.png%22%7D%2C%22content%22%3A%22%EB%9D%BC%EB%AC%B4%EC%A7%84%22%2C%22confirmid%22%3A854027579%7D%5D%2C%22graphicInfo%22%3A%5B%5D%2C%22roadviewInfo%22%3A%5B%5D%7D&amp;amp;mapWidth=490&amp;amp;mapX=755365&amp;amp;mapY=471723&amp;amp;map_hybrid=false&amp;amp;map_level=4&amp;amp;map_type=TYPE_MAP&amp;amp;rcode=4817067800&amp;amp;tel=055-762-0951&amp;amp;title=%EB%9D%BC%EB%AC%B4%EC%A7%84&quot; data-maps-mapx=&quot;755365&quot; data-maps-mapy=&quot;471723&quot; data-maps-thumbnail=&quot;https://ssl.daumcdn.net/map3/staticmap/image?center=755365%2C471723&amp;amp;lv=4&amp;amp;size=540x350&amp;amp;srs=WCONGNAMUL&amp;amp;markers=symbol%3Asc_marker%7Clocation%3A755366%2C471729&quot;&gt;&lt;/iframe&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAHjdH/btrtlnzKTRT/ctS1rG6k6bQOYf8A3HX8TK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAHjdH/btrtlnzKTRT/ctS1rG6k6bQOYf8A3HX8TK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAHjdH/btrtlnzKTRT/ctS1rG6k6bQOYf8A3HX8TK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAHjdH%2FbtrtlnzKTRT%2FctS1rG6k6bQOYf8A3HX8TK%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/esWSCR/btrtoAymux8/BzkSEV7pKL2vXMKkOP8Te1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/esWSCR/btrtoAymux8/BzkSEV7pKL2vXMKkOP8Te1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/esWSCR/btrtoAymux8/BzkSEV7pKL2vXMKkOP8Te1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FesWSCR%2FbtrtoAymux8%2FBzkSEV7pKL2vXMKkOP8Te1%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuBFTb/btrtjOSbPoN/kmsiTwRhkpdbgpHO657CAK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuBFTb/btrtjOSbPoN/kmsiTwRhkpdbgpHO657CAK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuBFTb/btrtjOSbPoN/kmsiTwRhkpdbgpHO657CAK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuBFTb%2FbtrtjOSbPoN%2FkmsiTwRhkpdbgpHO657CAK%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dscbyO/btrtjOSbPR6/iqmncJgQKfUksEAZe2rrJ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dscbyO/btrtjOSbPR6/iqmncJgQKfUksEAZe2rrJ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dscbyO/btrtjOSbPR6/iqmncJgQKfUksEAZe2rrJ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdscbyO%2FbtrtjOSbPR6%2FiqmncJgQKfUksEAZe2rrJ1%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0SXfc/btrtgrb7bdW/kDmqbD99Xr3cgTBxEt44T1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0SXfc/btrtgrb7bdW/kDmqbD99Xr3cgTBxEt44T1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0SXfc/btrtgrb7bdW/kDmqbD99Xr3cgTBxEt44T1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0SXfc%2Fbtrtgrb7bdW%2FkDmqbD99Xr3cgTBxEt44T1%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/423QY/btrtmVW3Gv4/b2OusD1tgJ1WPqAFAVhldk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/423QY/btrtmVW3Gv4/b2OusD1tgJ1WPqAFAVhldk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/423QY/btrtmVW3Gv4/b2OusD1tgJ1WPqAFAVhldk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F423QY%2FbtrtmVW3Gv4%2Fb2OusD1tgJ1WPqAFAVhldk%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbeyJk/btrtlnT2Ggo/90Tn5KFGW3d2e7Xjq0UnGK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbeyJk/btrtlnT2Ggo/90Tn5KFGW3d2e7Xjq0UnGK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbeyJk/btrtlnT2Ggo/90Tn5KFGW3d2e7Xjq0UnGK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbeyJk%2FbtrtlnT2Ggo%2F90Tn5KFGW3d2e7Xjq0UnGK%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;</description>
      <category>일상/먹고재비</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/55</guid>
      <comments>https://devpanda.tistory.com/55#entry55comment</comments>
      <pubDate>Thu, 24 Mar 2022 09:00:10 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트 논리연산자 단축평가</title>
      <link>https://devpanda.tistory.com/54</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;|| 는 or 연산, &amp;amp;&amp;amp;이 and 연산인건 아는데,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647861748848&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{!movies &amp;amp;&amp;amp; &amp;lt;h4&amp;gt;Loading...&amp;lt;/h4&amp;gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에서 'movie' state가 undefined일 때 왜 우항의 로딩이 렌더링 되는지 궁금해서 찾아봤더니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단축평가라는게 존재했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 좌항이 true일때와 false 일 때 존재하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;true&lt;/b&gt; || something 일 때 우항을 볼 필요도 없이 좌항 값이 반환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;ex)&lt;/p&gt;
&lt;pre id=&quot;code_1647862058165&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;apple&quot; || false; // &quot;apple&quot; 
&quot;apple&quot; || true; // &quot;apple&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;false&lt;/b&gt; || something 일 때 우항 값이 반환된다.&lt;/p&gt;
&lt;pre id=&quot;code_1647862157473&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apple&quot; &amp;amp;&amp;amp; &quot;banana&quot; // &quot;banana&quot;&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;a href=&quot;https://curryyou.tistory.com/193&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://curryyou.tistory.com/193&lt;/a&gt;&amp;nbsp;[카레유]&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <category>&amp;amp;&amp;amp;</category>
      <category>||</category>
      <category>논리연산자</category>
      <category>단축평가</category>
      <category>자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/54</guid>
      <comments>https://devpanda.tistory.com/54#entry54comment</comments>
      <pubDate>Wed, 23 Mar 2022 09:29:45 +0900</pubDate>
    </item>
    <item>
      <title>익명함수와 즉시실행함수표현(IIFE)</title>
      <link>https://devpanda.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;익명함수 : 함수의 이름이 생략된 함수&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;Screen Shot 2022-03-21 at 8.08.38 PM.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;1668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pDLgI/btrwtBoJXqR/Ij6gc8OEvfCSvFidZMsWz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pDLgI/btrwtBoJXqR/Ij6gc8OEvfCSvFidZMsWz1/img.png&quot; data-alt=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pDLgI/btrwtBoJXqR/Ij6gc8OEvfCSvFidZMsWz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpDLgI%2FbtrwtBoJXqR%2FIj6gc8OEvfCSvFidZMsWz1%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;1632&quot; height=&quot;1668&quot; data-filename=&quot;Screen Shot 2022-03-21 at 8.08.38 PM.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;1668&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;차이점은 어디서 오냐면, 위에서 언급한&amp;nbsp;호이스팅의 개념에서 온다. &lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;일반함수의 경우,&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt; 함수 전체가 전부 맨 위로 올라가므로 함수를 호출하는 위치에 상관없이 사용될 수 있다고 했다.&lt;/b&gt;&lt;/span&gt; 반면, 리터럴 방식으로 사용되는 익명 함수의 경우, 호이스팅 시 함수를 담는 변수의 선언부만 위로 올라가고, 익명 함수 자체는 변수가 호출되었을 때 실행되기 때문에, &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;선언부가 호출 위치보다 위에 있어야 한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;(티스토리 사막하는 개발여우님 블로그 -&amp;nbsp;&lt;a href=&quot;https://dev-note-97.tistory.com/273&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dev-note-97.tistory.com/273&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;br /&gt;즉시실행함수&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1647861012516&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(function () {
    statements
})();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Glossary/Self-Executing_Anonymous_Function&quot;&gt;Self-Executing Anonymous Function&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;으로 알려진 디자인 패턴이고 크게 두 부분으로 구성된다. 첫 번째는 괄호((), Grouping Operator)로 둘러싸인 익명함수(Anonymous Function)이다. 이는 전역 스코프에 불필요한 변수를 추가해서 오염시키는 것을 방지할 수 있을 뿐 아니라&amp;nbsp;IIFE 내부안으로&amp;nbsp;다른 변수들이&amp;nbsp;접근하는 것을 막을 수 있는 방법이다.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;두 번째 부분은 즉시 실행 함수를 생성하는 괄호()이다. 이를 통해 &lt;b&gt;자바스크립트 엔진은 함수를 즉시 해석해서 실행한다.&lt;/b&gt;&lt;/i&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;async 함수를&lt;/p&gt;
&lt;pre id=&quot;code_1647860340107&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  useEffect(() =&amp;gt; {
    (async () =&amp;gt; {
      const response = await fetch(`https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`)
      const json = await response.json();
  }, []);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깔끔하게 익명함수로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(괄호가 많아 지저분해보일지라도)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1647860272433&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    (async () =&amp;gt; {
      const { results } = await (
        await fetch(
          `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
        )
      ).json();
    })();
  }, []);&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발/자바스크립트</category>
      <category>익명함수</category>
      <category>자바스크립트</category>
      <category>즉시실행함수</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/53</guid>
      <comments>https://devpanda.tistory.com/53#entry53comment</comments>
      <pubDate>Tue, 22 Mar 2022 07:16:03 +0900</pubDate>
    </item>
    <item>
      <title>[NextJS] 넥스트JS 개념</title>
      <link>https://devpanda.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Node.js를 기반으로 구축된, 리액트 서버사이드 렌더링 프레임워크&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 자바스크립트 라이브러리, 넥스트는 프레임워크.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘의 가장 큰 차이는 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Inversion of Control&quot;(통제의 역전)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8; color: #000000;&quot;&gt;라이브러리에서 메서드를 호출하면 사용자가 제어할 수 있다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffc1c8; color: #000000;&quot;&gt;그러나 프레임워크에서는 제어가 역전되어 프레임워크가 사용자를 호출한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;라이브러리&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;사용자가 파일 이름이나 구조 등을 정하고, 모든 결정을 내림&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;프레임워크&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;파일 이름이나 구조 등을 정해진 규칙에 따라 만들고 따름&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;=&amp;gt; 리액트에서는 Component, Rount 등 원하는 위치와 파일명으로 자유롭게 import, export해서 사용했지만&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;넥스트JS에서는 클라이언트에게 보낼 화면을 pages폴더 안에 export default로 명시해줘야한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;파일명은 url이 되고 함수 이름은 상관없다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-03-21 at 10.02.47 AM.png&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;1236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DvMaw/btrwDNBGF0O/zJPkkT5WBeYt3PtBfSIdwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DvMaw/btrwDNBGF0O/zJPkkT5WBeYt3PtBfSIdwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DvMaw/btrwDNBGF0O/zJPkkT5WBeYt3PtBfSIdwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDvMaw%2FbtrwDNBGF0O%2FzJPkkT5WBeYt3PtBfSIdwk%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;341&quot; height=&quot;618&quot; data-filename=&quot;Screen Shot 2022-03-21 at 10.02.47 AM.png&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;1236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넥스트JS의 장점?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트가 OFF된 상황에서도 html 요소는 렌더된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 div#root가 자바스크립트 객체를 불러오지 못하기 때문에 noscript 태그 안의 요소만 렌더링된다.&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;넥스트JS는 미리 html요소를 불러오고(pre render) 이후 자바스크립트,리액트 가 주입된다(hydration)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;빈 객체를 반환하는 페이지와 달리 이미 html요소들이 있기에 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;봇이 수집하는 검색엔진최적화에서도&lt;span&gt;&amp;nbsp;유리하다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <category>NextJS</category>
      <category>SSR</category>
      <category>자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/52</guid>
      <comments>https://devpanda.tistory.com/52#entry52comment</comments>
      <pubDate>Mon, 21 Mar 2022 10:49:37 +0900</pubDate>
    </item>
    <item>
      <title>[네스트js] 컨트롤러, 프로바이더, 모듈 + validation</title>
      <link>https://devpanda.tistory.com/51</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Controllers&lt;/span&gt; &lt;/b&gt;are responsible for handling incoming&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;requests&lt;/b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and returning&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;responses&lt;/b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to the client.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;(like a router in express)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;Providers&lt;/b&gt;&lt;/span&gt; are a fundamental concept in Nest. Many of the basic Nest classes may be treated as a provider &amp;ndash; services, repositories, factories, helpers, and so on. The main idea of a provider is that it can be&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;injected&lt;/b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as dependency; this means objects can create various relationships with each other, and the function of &quot;wiring up&quot; instances of objects can largely be delegated to the Nest runtime system.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;A &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;module&lt;/b&gt; &lt;/span&gt;is a class annotated with a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;@Module()&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;decorator. The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;@Module()&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;decorator provides metadata that&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Nest&lt;/b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;makes use of to organize the application structure.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내장 validationPipe를 사용하기 위해선 calss-validator와 transformer를 설치해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1647478650453&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i class-validator class-transformer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;Validation&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;웹 애플리케이션으로 전송되는 데이터의 &lt;b&gt;검증을&lt;/b&gt; 도와줍니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;들어오는 요청을 자동으로 검증하기 위해 Nest는 즉시 사용할 수 있는 여러 파이프를 제공합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;ValidationPipe는 강력한 클래스 유효성 검사기 패키지와 선언적 유효성 검사 데코레이터를 사용합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;a href=&quot;https://docs.nestjs.com/techniques/validation&quot;&gt;https://docs.nestjs.com/techniques/validation&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;자동 검증&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;애플리케이션 수준에서 ValidationPipe를 바인딩하는 것으로 시작하겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;따라서 모든 엔드포인트가 잘못된 데이터를 수신하지 못하도록 보호됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;a href=&quot;https://docs.nestjs.com/techniques/validation&quot;&gt;https://docs.nestjs.com/techniques/validation&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;whitelist&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;true로 설정하면 유효성 검사기는 class-validator의 유효성 검사 데코레이터를 적어도 하나라도 사용하지 않은 모든 속성 객체를 제거합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;예시)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 측에서 전송한 데이터가 다음일 경우&lt;/p&gt;
&lt;pre id=&quot;code_1647479325795&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
　 &quot;title&quot;: &quot;Tenet&quot;,
　 &quot;year&quot;: 2020,
　 &quot;genres&quot;: [&quot;Action&quot;, &quot;Sci-Fi&quot;],
　 &quot;hack&quot;: &quot;by me&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;whitelist: true 로 설정했을 때는 데코레이터가 없는 속성&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;(&lt;b&gt;&quot;hack&quot;)은 제거되어 저장됩니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;forbidNonWhitelisted&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;true로 설정하면 화이트리스트에 없는 속성을 제거하는 대신 유효성 검사기가 예외를 throw합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;예시)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 전송 데이터가 다음일 경우&lt;/p&gt;
&lt;pre id=&quot;code_1647479429174&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
　 &quot;title&quot;: &quot;Tenet&quot;,
　 &quot;year&quot;: 2020,
　 &quot;genres&quot;: [&quot;Action&quot;, &quot;Sci-Fi&quot;],
　 &quot;hack&quot;: &quot;by me&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&quot;hack&quot;이라는 속성은 화이트리스트에 존재하지 않으므로 HttpException 을 던집니다.(statusCode 400)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;transform (자동 형변환)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;네트워크를 통해 들어오는 payload는 일반 JavaScript 객체입니다. ValidationPipe는 payload를 DTO 클래스에 따라 유형이 지정된 객체로 자동 변환할 수 있습니다. 자동 변환을 활성화하려면 transform을 true로 설정하십시오. 이 동작을 전역적으로 활성화하려면 전역 파이프에서 옵션을 설정합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;```&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;app.useGlobalPipes(&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;new ValidationPipe({&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;transform: true,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;}),&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;```&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;a href=&quot;https://docs.nestjs.com/techniques/validation#transform-payload-objects&quot;&gt;https://docs.nestjs.com/techniques/validation#transform-payload-objects&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1647478888285&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Documentation | NestJS - A progressive Node.js framework&quot; data-og-description=&quot;Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac&quot; data-og-host=&quot;docs.nestjs.com&quot; data-og-source-url=&quot;https://docs.nestjs.com/techniques/validation#transform-payload-objects&quot; data-og-url=&quot;https://docs.nestjs.com&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kTNp2/hyNI7pxg9N/HnEIhmHtOk4Cc6hlSJTW7K/img.png?width=820&amp;amp;height=429&amp;amp;face=0_0_820_429&quot;&gt;&lt;a href=&quot;https://docs.nestjs.com/techniques/validation#transform-payload-objects&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.nestjs.com/techniques/validation#transform-payload-objects&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kTNp2/hyNI7pxg9N/HnEIhmHtOk4Cc6hlSJTW7K/img.png?width=820&amp;amp;height=429&amp;amp;face=0_0_820_429');&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;Documentation | NestJS - A progressive Node.js framework&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.nestjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;출처- 노마드코더 sugar님(&lt;a href=&quot;https://nomadcoders.co/users/sugar&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://nomadcoders.co/users/sugar&lt;/a&gt;), snowball님(&lt;a href=&quot;https://nomadcoders.co/users/carrotcold&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://nomadcoders.co/users/carrotcold&lt;/a&gt;)&lt;/p&gt;</description>
      <category>개발/자바스크립트</category>
      <author>대왕판다</author>
      <guid isPermaLink="true">https://devpanda.tistory.com/51</guid>
      <comments>https://devpanda.tistory.com/51#entry51comment</comments>
      <pubDate>Thu, 17 Mar 2022 16:00:35 +0900</pubDate>
    </item>
  </channel>
</rss>