<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개 발 자 국</title>
    <link>https://settong.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 23 Jun 2026 10:05:17 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>settong</managingEditor>
    <image>
      <title>개 발 자 국</title>
      <url>https://tistory1.daumcdn.net/tistory/5906989/attach/db30144896de4326a65a5fe1d281f957</url>
      <link>https://settong.tistory.com</link>
    </image>
    <item>
      <title>OS 기술 면접 대비</title>
      <link>https://settong.tistory.com/entry/OS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스와 스레드의 차이&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;프로세스는 실행중인 프로그램을 말한다. 메모리 영역을 다른 프로세스와 공유하지 않습니다.&lt;/li&gt;&lt;li&gt;스레드는 프로세스 내에서 Stack만 따로 할당 받아 사용한다. 그 외의 메모리 영역을 다른 스레드와 공유합니다.&lt;/li&gt;&lt;li&gt;스레드는 프로세스 내에 존재하며, 프로세스가 할당받은 자원을 이용합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;멀티 프로세스와 멀티 스레드의 특징&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;멀티 프로세스는 두 개 이상의 프로세스가 실행되는 환경을 말합니다.&lt;/li&gt;&lt;li&gt;각 프로세스는 독립적인 메모리를 할당 받으므로, 서로 영향을 미치지 않습니다.&lt;/li&gt;&lt;li&gt;멀티 스레드는 두 개 이상의 스레드가 실행되는 환경을 말합니다.&lt;/li&gt;&lt;li&gt;멀티 스레드는 서로 자원을 공유할 수 있기 때문에 동기화에 주의를 기울여야 합니다.&lt;/li&gt;&lt;li&gt;한 스레드에 문제가 생기면 다른 프로세스에도 영향을 미칠 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;멀티 스레드의 동시성과 병렬성&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;동시성이란 싱글코어에서 여러 스레드가 번갈아 실행하며 동시에 실행하는 것처럼 보이는 것을 말합니다.&lt;/li&gt;&lt;li&gt;병렬성이란 멸티코어에서 한 개 이상의 스레드를 포함하는 각 코어들이 동시에 실행하는 것을 말합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;데드락이란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;둘 이상의 프로세스가 자원을 점유한 상태에서, 서로의 자원을 요구하며 무한정 기다리는 상황을 말합니다.&lt;/li&gt;&lt;li&gt;데드락의 4가지 조건은 비선점, 순환대기, 점유대기, 상호배제 입니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;콘보이(Convoy Effect) 현상이란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;작업시간이 긴 프로세스가 먼저 큐에 진입하여 다른 프로세스들의 실행시간이 전부 늦어지는 현상을 말합니다.&lt;/li&gt;&lt;li&gt;FCFS(First Come First Served) 스케줄링 알고리즘 사용 시 콘보이 현상이 발생할 수 있습니다.&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;선점형은 하나의 프로세스가 CPU를 사용하고 있을 때 다른 프로세스 강제로 CPU를 빼앗아 사용할 수 있는 것을 말합니다.&lt;/li&gt;&lt;li&gt;비선점형은 하나의 프로세스가 CPU를 사용하고 있을 때 작업이 끝날 때 까지 다른 프로세스가 CPU를 사용할 수 없는 것을 말합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;동기와 비동기의 차이&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;동기는 순차적으로 테스크를 수행하고, 비동기는 병렬적으로 테스크를 수행합니다.&lt;/li&gt;&lt;li&gt;동기 방식은 설계가 매우 간단하고 직관적이지만, 결과가 주어질 때 까지 대기만 해야한다는 단점이 있습니다.&lt;/li&gt;&lt;li&gt;비동기 방식은 동기 방식에 비해 복잡하지만, 결과가 주어지기 전에 다른 작업을 수행할 수 있으므로 자원을 효율적으로 사용할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;임계영역에 대한 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;임계영역이란 프로세스가 공유자원을 접근할 때 문제가 발생하지 않도록 하나의 프로세스만 이용할 수 있도록 보장해야하는 영역을 말합니다.&lt;/li&gt;&lt;li&gt;임계영역 문제 해결을 위해서는 상호배제, 진행, 한정대기 조건을 충족해야 합니다.&lt;/li&gt;&lt;li&gt;상호배제 : 하나의 프로세스가 임계영역에 들어가 있다면 다른 프로세스는 들어갈 수 없어야 합니다.&lt;/li&gt;&lt;li&gt;진행 : 임계영역에 비어있고 들어가고자 하는 프로세스가 여러개라면, 반드시 임계영역에 들어갈 프로세스를 결정해야한다.&lt;/li&gt;&lt;li&gt;한정대기: 기아상태 방지를 위해, 한번 임계구역에 들어간 프로세스는 다시 임계영역에 들어갈 때 제한을 두어야 한다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;뮤텍스와 세마포어&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;뮤텍스와 세마포어는 공유자원에 대한 접근을 제어하기 위한 기법입니다.&lt;/li&gt;&lt;li&gt;뮤텍스는 Lock을 사용해, 하나의 프로세스나 스레드를 단독으로 실행시킵니다.&lt;/li&gt;&lt;li&gt;세마포어는 동시에 접근 가능한 스레드 개수를 지정할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이지 교체 알고리즘&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;FIFO(First In First Out) : 메모리에 올라온 지 가장 오래된 페이지를 교체합니다. 구현이 가장 쉽습니다.&lt;/li&gt;&lt;li&gt;LRU(Least Recently Used) : 가장 오래 사용되지 않은 페이지를 교체합니다.&lt;/li&gt;&lt;li&gt;LFU(Least Frequently Used) : 참조횟수가 가장 작은 페이지를 교체합니다.&lt;/li&gt;&lt;li&gt;MFU(Most Frequentlry Used) : 참조횟수가 가장 많은 페이지를 교체합니다.&lt;/li&gt;&lt;li&gt;Optimal : 앞으로 사용될 페이지를 예측하여, 오랫동안 사용되지 않을 페이지를 교체합니다. 실제로 구현이 불가능한 알고리즘으로, 다른 페이지 교체 알고리즘 평가 지표나 연구 목적으로 사용됩니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Context Switching이란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;멀티프로세스 환경에서 '동시성'을 위해 하나의 프로세스가 CPU를 사용하고 있을 때 다른 프로세스로 전환하기 위한 작업을 말합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 콜 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;운영체제는 유저 모드와 커널 모드로 나뉘어 동작합니다.&lt;/li&gt;&lt;li&gt;유저 모드는 하드웨어에 직접적으로 접근할 수 없고, 커널모드는 모든 시스템 메모리와 하드웨어 등에 직접 접근이 가능합니다.&lt;/li&gt;&lt;li&gt;사용자가 커널모드로 접근하기 위한 인터페이스가 시스템 콜입니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;가상메모리 셜명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;컴퓨터가 실제로 이용 가능한 메모리 자원을 추상화 하여 사용자들에게 더 큰 메모리로 보이게 만드는 것을 의미합니다.&lt;/li&gt;&lt;li&gt;가상메모리의 공간은 거의 무한하기 때문에 프로세스들끼리 메모리 침범이 일어날 여지를 줄이게 됩니다.&lt;/li&gt;&lt;li&gt;페이지 테이블은 가상메모리 시스템에서 가상 주소를 실제 주소로 변환해주는 테이블을 말합니다. 이를 이용하여 실제 주소로 접근할 수 있게 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이지 폴트 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;가상메모리에서 참조하려는 메모리 영역이 RAM에 존재하지 않을 때 접근을 시도하면 페이지 폴트 예외가 발생하고 스와핑이 일어나게 됩니다.&lt;/li&gt;&lt;li&gt;스와핑은 메모리 확보를 위해 RAM의 일부를 디스크로 내보내고(스왑 아웃), 디스크에서 RAM에 필요한 페이지를 불러오는(스왑 인) 작업을 말합니다.&lt;/li&gt;&lt;li&gt;페이지 폴트가 빈번하게 일어나 스와핑을 자주 하게되는 현상을 '스레싱'이라고 한다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;메모리 단편화란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;메모리 단편화란 메모리 공간에 사용되지 못하는 공간이 발생하는 현상을 말합니다.&lt;/li&gt;&lt;li&gt;내부 단편화란, 메모리를 연속적으로 할당할 때 고정 크기로 분할하면서, 메모리 블록 내에 사용되지 않는 공간이 발생하는 것을 말합니다.&lt;/li&gt;&lt;li&gt;외부 단편화란, 불연속으로 할당하면서, 메모리 블록 밖의 공간이 여러 작은 조각으로 나뉘어서 사용되지 못하는 것을 말합니다.&lt;/li&gt;&lt;/ul&gt;</description>
      <category>Computer Science/Operating System</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/237</guid>
      <comments>https://settong.tistory.com/entry/OS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84#entry237comment</comments>
      <pubDate>Thu, 20 Mar 2025 22:58:27 +0900</pubDate>
    </item>
    <item>
      <title>Java 기술 면접 대비</title>
      <link>https://settong.tistory.com/entry/Java-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dev-coco.tistory.com/153&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://dev-coco.tistory.com/153 참고&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;신입 개발자 기술면접 질문 정리 - 자바&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;  Java의 특징을 설명해주세요.Java는 객체지향 프로그래밍 언어입니다. 기본 자료형을 제외한 모든 요소들이 객체로 표현되고, 객체 지향 개념의 특징인 캡슐화, 상속, 다형성이 잘 적용된 언어&quot; data-og-host=&quot;dev-coco.tistory.com&quot; data-og-source-url=&quot;https://dev-coco.tistory.com/153&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bD7Lfv/hyYvsJwJ73/kN2XZ5f5JYNVKNmqGJwAHk/img.png?width=450&amp;amp;height=249&amp;amp;face=0_0_450_249,https://scrap.kakaocdn.net/dn/yig1V/hyYvh2iuDn/kt9kllKP8n02BSonkqU7O1/img.png?width=450&amp;amp;height=249&amp;amp;face=0_0_450_249,https://scrap.kakaocdn.net/dn/bN18dM/hyYr0OwPrC/HUBqKdxPorqx5AqfZBQA21/img.png?width=720&amp;amp;height=422&amp;amp;face=0_0_720_422&quot; data-og-url=&quot;https://dev-coco.tistory.com/153&quot;&gt;&lt;a href=&quot;https://dev-coco.tistory.com/153&quot; target=&quot;_blank&quot; data-source-url=&quot;https://dev-coco.tistory.com/153&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bD7Lfv/hyYvsJwJ73/kN2XZ5f5JYNVKNmqGJwAHk/img.png?width=450&amp;amp;height=249&amp;amp;face=0_0_450_249,https://scrap.kakaocdn.net/dn/yig1V/hyYvh2iuDn/kt9kllKP8n02BSonkqU7O1/img.png?width=450&amp;amp;height=249&amp;amp;face=0_0_450_249,https://scrap.kakaocdn.net/dn/bN18dM/hyYr0OwPrC/HUBqKdxPorqx5AqfZBQA21/img.png?width=720&amp;amp;height=422&amp;amp;face=0_0_720_422')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;신입 개발자 기술면접 질문 정리 - 자바&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;  Java의 특징을 설명해주세요.Java는 객체지향 프로그래밍 언어입니다. 기본 자료형을 제외한 모든 요소들이 객체로 표현되고, 객체 지향 개념의 특징인 캡슐화, 상속, 다형성이 잘 적용된 언어&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;dev-coco.tistory.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java의 특징 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Java는 객체지향 프로그래밍언어로, 다형성, 상속, 캡슐화, 추상화 등의 특징을 가집니다.&lt;/li&gt;&lt;li&gt;JVM 위에서 구동되어 운영체제에 독립적입니다. 하지만 이 때문에 실행 속도가 상대적으로 느립니다.&lt;/li&gt;&lt;li&gt;GC가 자동으로 메모리를 관리해줍니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;JVM에 대한 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;JVM은 Java Virtual Machine의 약자로, Java가 운영체제에 독립적일 수 있게 합니다.&lt;/li&gt;&lt;li&gt;클래스 로더 영억, 런타임 데이터 영역, 실행 엔진 영역으로 나뉩니다.&lt;/li&gt;&lt;li&gt;클래스 로더는 바이트파일을 JVM 메모리에 로드하는 역할을 하며, 동적으로 런타임 데이터 영역에 클래스들이 배치됩니다.&lt;br&gt;실행 엔진에서 바이트파일을 실행시키며, GC로 메모리 관리를 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java의 컴파일 과정&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;.java 확장자의 파일을 Java 컴파일러로 .class 확장자의 바이트파일로 컴파일합니다.&lt;/li&gt;&lt;li&gt;컴파일된 바이트파일을 클래스 로더가 JVM 메모리에 로드합니다.&lt;/li&gt;&lt;li&gt;실행 엔진이 해당 파일을 실행시킵니다. 처음에는 인터프리터 방식으로 실행시키고, 자주 사용되는 것들은 JIT(Just In Time)로 실행시킵니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Overriding과 Overloading&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Overriding이란 인터페이스나 부모 클래스에서 상속받은 메소드를 재정의하는 것을 의미합니다.&lt;/li&gt;&lt;li&gt;Overloading이란 같은 이름의 메소드를 변수의 수 등을 다르게 하여 여러개 정의하는 것을 의미합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체지향 프로그래밍(OOP)이란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;모든 요소들을 객체의 형태로 바라보고, 각 객체들의 역할에 따라 상호작용하도록 하는 것을 의미합니다.&lt;/li&gt;&lt;li&gt;즉, 기능 중심이 아닌, '누가 어떤 역할을 하는가?'를 중심으로 합니다.&lt;/li&gt;&lt;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;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;객체지향 설계 원칙은 SOLID를 따릅니다.&lt;/li&gt;&lt;li&gt;SRP (단일 책임 원칙) : 하나의 클래스는 하나의 역할만 수행다는 원칙입니다.&lt;/li&gt;&lt;li&gt;OCP (개방 폐쇄 원칙) : 확장에는 열려있고, 수정에는 닫혀있다는 원칙입니다.&lt;/li&gt;&lt;li&gt;LSP (리스코프 치환 원칙) : 하위타입은 항상 상위타입을 대체할 수 있어야 한다는 원칙입니다.&lt;/li&gt;&lt;li&gt;ISP (인터페이스 분리 원칙) : 인터페이스의 메소드를 최소화하여, 여러개의 인터페이스로 분리하라는 원칙입니다.&lt;/li&gt;&lt;li&gt;DIP (의존성 역전 원칙) : 구체적인 클래스보다 수정 가능성이 덜한 추상 클래스나 인터페이스와 관계를 맺도록 하는 원칙입니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;try-with-resources란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;try-catch-finally 구문을 보완하고자 등장한 개념입니다.&lt;/li&gt;&lt;li&gt;try구문에 자원 객체를 전달하면, try 블록 종료 시 자원 할당이 자동으로 해제됩니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;불변 객체란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;불변 객체란 데이터 내부의 상태가 변하지 않는 객체를 말합니다.&lt;/li&gt;&lt;li&gt;해시값 변경이 없기 때문에 해시를 사용하는 Map이나 Set으로 관리하기 좋습니다.&lt;/li&gt;&lt;li&gt;자원 동기화가 필요 없어 멀티 스레드 환경에서도 안전하게 사용 가능합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;불변객체를 만드는 방법&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;final 키워드로 불변객체를 만들 수 있습니다.&lt;/li&gt;&lt;li&gt;다만, 참조 자료형의 경우 내부 값들까지 불변으로 유지해야하기 때문에, 참조하는 객체의 내부 값들을 복사하여 저장하는 형태로 만들 수 있습니다.&lt;/li&gt;&lt;li&gt;이를 방어적 복사(defensive copy)라고 합니다.&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;추상 클래스는 abstract로 정의되어 있거나, 추상 메소드를 포함한 클래스를 말합니다.&lt;/li&gt;&lt;li&gt;인터페이스는 모든 메소드가 추상 메소드여야 합니다.&lt;/li&gt;&lt;li&gt;클래스는 다중상속이 불가능하지만, 인터페이시는 가능합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;싱글톤 패턴이란?&lt;/h3&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;li&gt;인스턴스가 1개만 존재하는 것을 보장하고 싶은 경우 사용합니다.&lt;/li&gt;&lt;li&gt;또는 동일한 인스턴스를 자주 사용해야 하는 경우 메모리 낭비를 방지하기 위해 사용합니다.&lt;/li&gt;&lt;li&gt;대표적인 예로는 Spring의 Bean이 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Garbage Collection이란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Java에서 자동으로 메모리를 관리해주는 기법을 말합니다.&lt;/li&gt;&lt;li&gt;JVM의 엔진 영역에서 구동됩니다.&lt;/li&gt;&lt;li&gt;GC는 '대부분의 객체는 생명주기가 짧고, 오래 사용된 객체는 계속해서 오래 사용될 가능성이 높다'라는 가정하에 설계되었습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Garbage Colloection 과정&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Young Generation과 Old Generation으로 나뉘며, Young Generation에서 일어나는 GC 작업을 Minor GC라고 합니다.&lt;/li&gt;&lt;li&gt;Young Generation은 에덴 영역과 서바이버 영역으로 나뉘어져 있습니다. 에덴 영역에 새로운 객체들을 저장하고, 사용되는 객체들은 나이를 부여하며 서바이버 영역에 존재하게 합니다.&lt;/li&gt;&lt;li&gt;Minor GC 작업 시 사용되지 않는 객체를 정리하고 사용되는 객체들의 나이가 임계치를 넘어설 경우 Old Generation 영역에 저장합니다.&lt;/li&gt;&lt;li&gt;Old Generation 영역이 가득차게 되면 Major GC를 수행하여, 객체들을 정리합니다.&lt;/li&gt;&lt;li&gt;GC 작업은 모든 스레드가 중단된 후 이루어집니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바의 메모리 영역에 대한 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;자바의 메모리 영역은 메소드 영역, 힙 영역, 스택 영역으로 나뉘어집니다.&lt;/li&gt;&lt;li&gt;메소드 영역은 static변수들이나 method들이 저장되며, 프로그램 실행부터 종료까지의 생명주기를 갖습니다.&lt;/li&gt;&lt;li&gt;힙 영역은 프로그램이 실행되며 생성된 객체들이 저장됩니다. GC에 의해 관리되어지는 영역입니다.&lt;/li&gt;&lt;li&gt;스택 영역은 메소드가 실행되며 생성된 변수들이 저장되는 공간입니다. 메소드 호출부터 종료까지의 생명주기를 갖습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;클래스/객체/인스턴스 의 차이&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;클래스는 객체를 생성하기 위한 설계도, 틀을 의미합니다.&lt;/li&gt;&lt;li&gt;클래스를 기반으로 생성되는 것을 객체라고 합니다.&lt;/li&gt;&lt;li&gt;객체에 실제 메모리가 할당되어 사용되는 것을 인스턴스라고 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자에 대한 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;클래스와 같은 이름을 가진 메소드로, 객체를 생성할 때 호출합니다.&lt;/li&gt;&lt;li&gt;명시적으로 생성자를 정의하지 않아도 default로 생성되며, 이 경우에는 파라미터를 아무것도 받지 않습니다.&lt;/li&gt;&lt;li&gt;오버로딩으로 여러 생성자를 생성할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Wrapper Class, Boxing과 Unboxing 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;int, long과 같은 기본 자료형을 객체로 표현한 것을 Wrapper Class라고 합니다.&lt;/li&gt;&lt;li&gt;기본자료형을 Wrapper Class로 변환하는 작업을 Boxing, 반대의 작업을 Unboxing이라고 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Synchronized 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;멀티스레드 환경에서 한 스레드가 특정 자원을 사용하고 있을 때 다른 자원이 사용하지 못하도록 하는 것입니다.&lt;/li&gt;&lt;li&gt;변수와 메소드에 Synchronized 키워드를 사용해 동기화 할 수 있습니다.&lt;/li&gt;&lt;li&gt;Synchronized 키워드 남발 시 프로그램 성능이 저하될 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;new String()과 리터럴(&quot;&quot;) 차이&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;리터럴로 생성한 문자열 객체는 힙메모리의 String pool에 저장됩니다.&lt;/li&gt;&lt;li&gt;만약 동일한 값의 문자열을 리터럴로 생성하면, String pool에 저장된 문자열 객체를 동일하게 사용합니다.&lt;/li&gt;&lt;li&gt;생성자를 통해 문자열을 생성하면, 동일한 값의 문자열이여도 새로운 객체를 생성하여 사용하게 됩니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;String, StringBuffer, StringBuilder의 차이&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;String은 기본적으로 불변객체의 특성을 가집니다. 때문에 값 수정이 불가능합니다.&lt;/li&gt;&lt;li&gt;때문에 문자열 값이 빈번하게 바뀔 경우 String은 새로운 객체를 계속 생성하여 메모리 낭비를 발생시킵니다.&lt;/li&gt;&lt;li&gt;StringBuffer와 StringBuilder는 문자열 수정이 자유롭습니다.&lt;/li&gt;&lt;li&gt;StringBuilder의 경우 동기화를 지원하지 않아 싱글 스레드 환경에 적합합니다.&lt;/li&gt;&lt;li&gt;StringBuffer의 경우 동기화를 지원하여 멀티스레드 환경에 적합합니다.&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;private : 해당 클래스에서만 접근 가능.&lt;/li&gt;&lt;li&gt;(default) : 해당 패키지에서만 접근 가능.&lt;/li&gt;&lt;li&gt;protected : 해당 패키지내에서 접근 가능. 또는 다른 패키지에서 상속받아 자식 클래스에서 접근 가능.&lt;/li&gt;&lt;li&gt;public : 접근 제한 없음.&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;static 변수 선언부 : 클래스 로드 될 때 초기화 됩니다.&lt;/li&gt;&lt;li&gt;필드 변수 선언부 : 객체 생성 시 생성자 block보다 먼저 초기화 됩니다.&lt;/li&gt;&lt;li&gt;생성자 block : 객체 생성 시 가장 마지막에 초기화 됩니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;static 키워드란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;static 키워드를 사용한 변수나 메서드는 클래스 로드될 때 생성되어, 로딩이 완료하면 곧바로 사용 가능하다.&lt;/li&gt;&lt;li&gt;모든 객체가 메모리를 공유한다는 특징이 있고, 메소드 영역에 있기 때문에 GC의 관리를 받지 않습니다.&lt;/li&gt;&lt;li&gt;보통 자주 변하지 않는 값이나 공통으로 사용되는 값에 사용됩니다. '전역변수'와 같은 개념으로 접근할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Inner Class의 장점&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;서로 관련있는 클래스를 논리적으로 묶어서 표현할 수 있으므로 응집도를 높일 수 있다.&lt;/li&gt;&lt;li&gt;외부에서 내부 클래스에 접근하지 못하도록 캡슐화 하여, 보안을 높일 수 있다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Inner Class를 static으로 선언해야 하는 이유&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;내부 클래스는 암묵적으로 외부클래스 인스턴스를 참조합니다.&lt;/li&gt;&lt;li&gt;외부 클래스가 필요없어질 경우 GC가 이를 제거해야하지만, 내부클래스의 참조로 인해 제거가 되지 않을 수 있습니다.&lt;/li&gt;&lt;li&gt;때문에 static으로 선언하여 외부 클래스와 독립적으로 만드는 것입니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;리플렉션(Reflection)이란?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;리플렉션이란 구체적인 클래스의 타입을 알지 못해도 해당 클래스의 변수, 메소드 등에 접근할 수 있도록 하는 것을 말합니다.&lt;/li&gt;&lt;li&gt;제네릭과 달리 타입안정성을 보장하지 않습니다.&lt;/li&gt;&lt;li&gt;스프링 프레임워크의 어노테이션이 리플렉션을 활용한 기능이라고 알고 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Error와 Exception의 차이 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Error는 실행 중 일어날 수 있는 치명적인 오류를 말합니다. Error가 발생하게되면 프로그램이 비정상적으로 종료됩니다.&lt;/li&gt;&lt;li&gt;Exception은 Error에 비해 경미한 오류를 말합니다. 예외 처리를 통해 비정상적 종료를 예방할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;CheckedException과 UncheckedException&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;CheckedException은 실행 전 예측 가능한 예외들을 말하며, 반드시 예외처리를 수행해야 합니다.&lt;/li&gt;&lt;li&gt;UncheckedException의 경우 실행 후에야 알 수 있는 예외들을 말합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Optional API에 대한 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;개발 시 가장 자주 발생하는 오류는 NullPointException입니다.&lt;/li&gt; 
 &lt;li&gt;하지만 매번 null을 검증하는 코드를 작성해야 하는 경우, 코드가 복잡해지게 됩니다.&lt;/li&gt; 
 &lt;li&gt;이를 보완하고자 Java8부터 등장한 개념입니다.&lt;/li&gt; 
 &lt;li&gt;&lt;code&gt;Optional&amp;lt;T&amp;gt;&lt;/code&gt;를 통해 null을 사용하지 않고도 빈 값을 표현할 수 있게 하며, null로인한 예외가 발생하지 않게 합니다.&lt;/li&gt; 
&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Collection 프레임워크 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;다수의 데이터를 관리할 수 있는 프레임워크입니다.&lt;/li&gt;&lt;li&gt;List, Set, Map, Stack, Queue 등 다양한 자료구조를 지원합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;List, Set, Map, Stack, Queue의 특징&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;List: 데이터가 순서를 지키며 나열된 구조입니다. Array와 다르게 크기를 유연하게 조정할 수 있스빈다.&lt;/li&gt;&lt;li&gt;Set: 순서와 상관없이 중복을 허용하지 않으며 데이터를 저장합니다.&lt;/li&gt;&lt;li&gt;Map: key와 value 쌍으로 이루어진 데이터 구조입니다. key는 순서를 보장하지 않으며 중복을 허용하지 않습니다.&lt;/li&gt;&lt;li&gt;Stack: LIFO를 따르는 데이터 구조입니다.&lt;/li&gt;&lt;li&gt;Queue: FIFO를 따르는 데이터 구조입니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Set과 Map의 타입이 객체를 받을 때 중복 검사 방법&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Set과 Map의 구현체는 HashSet과 HashMap이 있습니다.&lt;/li&gt;&lt;li&gt;이들이 객체를 받을 때에는 equals를 재정의 하여 내부 데이터가 논리적으로 같은 값인지를 구별해야 합니다.&lt;/li&gt;&lt;li&gt;뿐만 아니라, hash코드로도 값을 비교하기 때문에 hashcode도 함께 재정의해야합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;제네릭이란? 왜 사용하는가?&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;제네릭이란 데이터 타입을 포괄적인 범위로 지정하는 것을 의미합니다.&lt;/li&gt;&lt;li&gt;데이터 범위를 넓히며 타입 안정성을 보장하고, 유연한 프로그래밍이 가능합니다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;final, finally, finalize의 차이 설명&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;final: 불변객체를 만들기 위한 키워드입니다.&lt;/li&gt;&lt;li&gt;finally: try-catch문에서 예외 발생 여부와 관계없이 실행되는 블록을 정의할 때 사용합니다.&lt;/li&gt;&lt;li&gt;finalize: GC에 의해 사용되는 메소드로 알고 있습니다. 사용하면 안되는 메소드입니다.&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;시스템 내부에서 사용되는 객체나 데이터들을 외부에서도 사용할 수 있도록 byte로 변환하는 과정을 말합니다.&lt;/li&gt;&lt;li&gt;반대로 byte데이터를 객체나 데이터로 변환하는 과정은 '역직렬화'라고 합니다.&lt;/li&gt;&lt;li&gt;직렬화 수행 시 SerialVersionUID를 통해 버전을 관리합니다.&lt;/li&gt;&lt;/ul&gt;</description>
      <category>Language/Java</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/236</guid>
      <comments>https://settong.tistory.com/entry/Java-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84#entry236comment</comments>
      <pubDate>Thu, 20 Mar 2025 20:10:43 +0900</pubDate>
    </item>
    <item>
      <title>equals와 hashCode 오버라이딩</title>
      <link>https://settong.tistory.com/entry/equals%EC%99%80-hashCode-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;equals와 hashCode&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java에서 `equals()`와 `hashCode()` 메서드는 모든 Java 객체의 부모 객체인 Object 클래스에 정의되어 있다.&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;`equals()`는 같은 객체인지(메모리 주소가 같은지) 확인하는 기능만 제공한다. (즉 `==`와 동일한 동작을 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`hashCode()`는 객체를 식별하는 정수값(해시코드)를 반환하는 메서드이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  중요한 규칙&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;`equals()`가 `true`이면&lt;span&gt;&amp;nbsp;&lt;/span&gt;`hashCode()`는 무조건 `true`이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;`hashCode()`가 `true`여도 `equals`는 `false`일 수 있다. ⬅ 해시 충돌이 발생할 수 있기 때문.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;equals&lt;/b&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;일반적인 객체에서의 equals 예시&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 `equals()`메서드 사용 예시이다.&lt;/p&gt;
&lt;pre id=&quot;code_1741622805830&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p1 = new Person(&quot;Jeny&quot;);
Person p2 = new Person(&quot;Jeny&quot;);
Person p3 = new Person(&quot;Lisa&quot;);
System.out.println(p1.equals(p2)); // false
System.out.println(p1.equals(p3)); // false&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;`p1`과 `p2`는 `new Person()`을 사용하여 각각 다른 메모리 공간에 생성된 객체이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`equals`는 메모리 주소를 비교하기 때문에 `p1.equals(p2)`는 `false`를 반환한다.&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;String 객체에서의 equals 예시&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1741622244839&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String s1 = new String(&quot;Hello&quot;);
String s2 = new String(&quot;Hello&quot;);
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❌&amp;nbsp; 분명 `new`를 사용하여 새로운 객체를 생성하였으므로 s1과 s2는 서로 다른 참조값을 가진다. 때문에 `s1.equals(s2)`는 false가 나와야하지만, 결과는 true이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗️`String`클래스는 기본적으로 `equals()`를 오버라이딩하여 문자열의 내용을 비교하도록 구현되어 있기 때문에,&amp;nbsp;`s1.equals(s2)`가 true를 반환하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;equals의 Override&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`String`클래스와 같이 객체의 내용으로 비교하도록 구현하고 싶다면 `equals()` 메서드를 오버라이딩해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1741623418447&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;

        Person person = (Person) obj;
        return name.equals(person.name);
    }
}&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;위 코드에서 `Person`객체의 name을 비교하고, name이 같은 문자열이면 `true`를 반환하도록 오버라이딩한 것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1741623607408&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p1 = new Person(&quot;Jeny&quot;);
Person p2 = new Person(&quot;Jeny&quot;);
Person p3 = new Person(&quot;Lisa&quot;);
System.out.println(p1.equals(p2)); // true
System.out.println(p1.equals(p3)); // false&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;때문에 첫번째 예시에서의 결과와 달리, `p1`과 `p2`의 name이 같기 때문에 `p1.equals(p2)`는 `true`를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`p1.equals(p3)`는 name이 서로 다르기 때문에 `true`를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;hashCode&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;hashCode의 필요&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`hashCode()`는 `HashSet`, `HashMap`, `HashTable`과 같은 해시 기반 컬렉션에서 주로 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 빠른 검색과 삽입을 가능하게 하고, 해시값을 기반으로 &quot;버킷&quot;을 찾아 빠르게 접근할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`hashCode()`가 충돌을 최소화하는 방식으로 구현되면, 검색 속도가 O(1)에 가까워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;hashCode의 Override&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드를 실행하면 아래와 같은 경고가 뜰 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1741623894045&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Warning: Overriding 'equals' without overriding 'hashCode'&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;말 그대로, `hashCode()`는 오버라이딩 하지 않고 `equals()`만 오버라이딩 했다는 경고 문구이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로, Java의 Object 문서에는  &lt;b&gt;`equals()`를 오버라이딩하면 `hashCode()`도 함께 오버라이딩&lt;/b&gt; 해야한다고 명시하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 컬렉션(`HashSet`, `HashMap`, `HashTable`)에서 객체를 비교할 때 `hashCode()`가 사용되기 때문이다.&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;`Person`객체에서 `equals()` 메서드만 오버라이딩 되었을 때 `HashSet`을 사용하는 예시이다.&lt;/p&gt;
&lt;pre id=&quot;code_1741624585701&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p1 = new Person(&quot;Jeny&quot;);
Person p2 = new Person(&quot;Jeny&quot;);

HashSet&amp;lt;Person&amp;gt; set = new HashSet&amp;lt;&amp;gt;();
set.add(p1);

System.out.println(p1.equals(p2)); // true
System.out.println(set.contains(p2)); // false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❌&amp;nbsp; p1과 p2는 같은 name을 가지고 있으므로 논리적으로 같은 객체이다(`p1.equals(p2) == true`). 하지만 `set`에 `p1`을 추가하고 `p2` 포함 여부를 살피면 `false`가 반환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗️이는 `hashCode()`를 오버라이딩 하지 않아 서로 다른 값이 반환되어 `HashSet`이 같은 객체로 인식하지 않기 때문이다.&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;이를 해결하기 위해 Person 객체의 hashCode()메서드를 오버라이딩한다.&lt;/p&gt;
&lt;pre id=&quot;code_1741624990052&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Objects;

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Person person = (Person) obj;
        return Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1741625079219&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p1 = new Person(&quot;Jeny&quot;);
Person p2 = new Person(&quot;Jeny&quot;);

HashSet&amp;lt;Person&amp;gt; set = new HashSet&amp;lt;&amp;gt;();
set.add(p1);

System.out.println(p1.equals(p2)); // true
System.out.println(set.contains(p2)); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 `set`에 `p1`을 추가하고 `p2` 포함 여부를 살피면 `true`가 반환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`hashCode()`가 `name`의 `hash`를 반환하도록 오버라이딩 했기 때문에, `name`이 같으면 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;논리적으로 &lt;/span&gt;같은 객체라고 판단한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`equals()`는 두 객체의 논리적 동등성을 비교하는데 사용된다. 내용 기반으로 객체를 비교할 수 있도록 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`hashCode()`는 해시 기반 컬렉션에서 성능을 최적화하는 데 중요한 역할을 한다. 효율적인 검색과 빠른 데이터 처리를 가능하게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 프로젝트에서 equals()와 hashCode()를 제대로 오버라이딩하지 않으면, 해시 기반 컬렉션(HashSet, HashMap, HashTable 등)을 사용할 때 예상치 못한 버그나 성능 저하가 발생할 수 있다. 예를 들어, 중복된 객체가 컬렉션에 추가되거나, 객체가 제대로 검색되지 않는 문제가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Language/Java</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/233</guid>
      <comments>https://settong.tistory.com/entry/equals%EC%99%80-hashCode-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9#entry233comment</comments>
      <pubDate>Tue, 11 Mar 2025 08:54:33 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] Embedded Redis 추가하기 (Mac 해결책)</title>
      <link>https://settong.tistory.com/entry/Spring-Boot-Embedded-Redis-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0-Mac-%ED%95%B4%EA%B2%B0%EC%B1%85</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;친구랑 작은 토이프로젝트를 기획하면서, Redis 를 사용할 일이 생겼다.&amp;nbsp;&lt;br&gt;일단 Redis 환경을 어떻게 구성할지에 대해 고민했다.&lt;br&gt;&amp;nbsp;&lt;br&gt;1. AWS 환경에서 사용&lt;br&gt;2. 로컬에서 Docker 환경으로 구성&lt;br&gt;3. 로컬에서 Docker 없이 직접 설치&lt;br&gt;&amp;nbsp;&lt;br&gt;일단 토이 프로젝트이고, 친구와 굳이 'Redis만을 위해' 배포를 할 필요성을 느끼지 못했기 때문에 1은 기각.&lt;br&gt;로컬에서 사용하는 것에 대해 고민하다가 친구가 'Embedded Redis'라는 것을 찾아왔다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Embedded Redis란?&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 내부에서 내장형 Redis 서버를 실행할 수 있도록 도와주는 방식이다.&lt;br&gt;보통 테스트환경에서 Redis를 별도로 설치하지 않고 애플리케이션과 함께 실행하고 싶을 때 사용한다.&lt;br&gt;&amp;nbsp;&lt;br&gt;Embedded Redis 의 장점은 다음과 같다.&lt;br&gt;로컬에서 개발할 때 Redis를 따로 설치하지 않아도 실행 가능하다. Docker를 사용할 필요도 없다.&lt;br&gt;Redis가 필요한 테스트 코드를 작성할 때, 실제 Redis서버를 사용하지 않고도 테스트가 가능하다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이러한 이유로, Docker 사용도 필요 없어? 직접 서버 실행도 아냐? 당장 진행하자! 하였고,&lt;br&gt;잘 실행 되는지 확인하기 위해 다음과 같이 구성했다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Embedded Redis 구성&lt;/b&gt;&lt;/h3&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 의존성 추가&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;build.gradle의 dependencies에 Embedded Redis 구성을 위한 의존성을 추가해줘야한다.&lt;br&gt;&lt;b&gt;build.gradle&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;dependencies {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// ...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// embedded redis
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;implementation 'it.ozimov:embedded-redis:0.7.2'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;implementation 'org.springframework.boot:spring-boot-starter-data-redis'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// ...
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;ozimov의 0.7.2버전이 자료를 찾아봤을 때 가장 많이 나오길래 해당 embedded redis를 추가해주었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Config 파일 만들기&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EmbeddedRedisConfig&lt;/b&gt;&lt;br&gt;Embedded Redis 설정에 대한 파일을 만들어줘야 한다.&lt;br&gt;local 환경에서만 실행되도록 profile을 설정했다.&lt;br&gt;실행 중인 Redis가 있으면 빈 포트를 찾아 실행시킨다.&lt;br&gt;start, stop 메서드로 Redis 서버 실행, 중지한다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Slf4j
@Profile({&quot;local&quot;})
@Configuration
public class EmbeddedRedisConfig {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Value(&quot;${spring.data.redis.port}&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private int redisPort;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private RedisServer redisServer;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@PostConstruct
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void start() throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int port = isRedisRunning() ? findAvailablePort() : redisPort;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisServer = new RedisServer(port);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisServer.start();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@PreDestroy
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void stop() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisServer.stop();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public int findAvailablePort() throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (int port = 10000; port &amp;lt;= 65535; port++) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Process process = executeGrepProcessCommand(port);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!isRunning(process)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return port;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new RuntimeException(&quot;No available ports found.&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Embedded Redis가 현재 실행중인지 확인
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private boolean isRedisRunning() throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return isRunning(executeGrepProcessCommand(redisPort));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * 해당 port를 사용중인 프로세스를 확인하는 sh 실행
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private Process executeGrepProcessCommand(int redisPort) throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String command = String.format(&quot;netstat -nat | grep LISTEN|grep %d&quot;, redisPort);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String[] shell = {&quot;/bin/sh&quot;, &quot;-c&quot;, command};

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Runtime.getRuntime().exec(shell);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * 해당 Process가 현재 실행중인지 확인
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private boolean isRunning(Process process) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String line;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StringBuilder pidInfo = new StringBuilder();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try (BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while ((line = input.readLine()) != null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pidInfo.append(line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} catch (Exception e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;log.error(e.getMessage());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return !pidInfo.isEmpty();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;RedisRepositoryConfig&lt;/b&gt;&lt;br&gt;Spring Boot에서 Redis를 연결하는 설정 파일이다.&lt;br&gt;Spring Data Redis를 사용하기 위한 기본적인 설정을 제공한다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration
@EnableRedisRepositories
public class RedisRepositoryConfig {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Value(&quot;${spring.data.redis.host}&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private String host;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Value(&quot;${spring.data.redis.port}&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private int port;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Bean
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public RedisConnectionFactory redisConnectionFactory() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return new LettuceConnectionFactory(host, port);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Bean
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public RedisTemplate&amp;lt;byte[], byte[]&amp;gt; redisTemplate() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RedisTemplate&amp;lt;byte[], byte[]&amp;gt; redisTemplate = new RedisTemplate&amp;lt;&amp;gt;();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisTemplate.setConnectionFactory(redisConnectionFactory());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return redisTemplate;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;테스트 해보기&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;RedisHash를 작성해보자&lt;br&gt;&lt;b&gt;Token 클래스&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@RedisHash(value = &quot;token&quot;, timeToLive = 60)
public class Token implements Serializable {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private String id;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private String value;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Token(String value) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.value = value;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;TokenRepository 인터페이스&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface TokenRepository extends CrudRepository&amp;lt;Token, String&amp;gt; {
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;EmbeddedRedisTest 테스트코드&amp;nbsp;&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@ActiveProfiles(&quot;local&quot;)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class EmbeddedRedisTest {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private TokenRepository tokenRepository;&amp;nbsp;&amp;nbsp;// @Autowired 적용

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@DisplayName(&quot;Token Save 테스트 성공&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@org.junit.jupiter.api.Test
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void saveTest(){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// given
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Token token = tokenRepository.save(new Token(&quot;token&quot;));

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// when
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Token savedToken = tokenRepository.save(token);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// then
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(savedToken).isNotNull();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Mac에서 문제 발생&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;Windows를 사용하는 친구는 해당 구성으로 테스트가 원활히 진행 되었다. 하지만 Mac을 사용하는 나는 계속 테스트가 실패했다. 오류 내용은 대충 Redis 서버가 실행되지 않았을 때 나는 오류였다.&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결론적으로, Redis-Server 바이너리 파일을 실행시키도록 했다.  &lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;Embedded Redis 를 Mac에서 지원하지 않기 때문에 TestContainers를 사용하라는 해결책이 대부분이었으나, 나는 애초에 Embedded Redis를 테스트 용도로 사용하는 것이 아니기 때문에 나에게 적용되지 않았다.&lt;br&gt;Mac M칩도 아닌 intel칩으로 작업을 하는 나는 Embedded Redis의 해당 오류에 대한 해결방법을 찾기 너무 어려웠다. M칩을 사용하는 사람들도 Redis 설치 파일로 작업하기로 했다는 글을 보았고, 해당 방법을 적용하였다.&lt;br&gt;Docker를 쓸까? 하는 고민도 살짝 했다. 하지만 내 OS의 문제였고, 친구의 OS에서는 정상 작동이 되었기 때문에 굳이 Docker를 사용해서 친구에게도 번거로운 작업을 추가하는 것보다, OS별로 Embedded Redis를 사용할지, Redis 서버를 사용할지 나누는 코드를 추가하는게 훨씬 간편하고 빠르고... 그렇다고 생각했다.&lt;br&gt;&amp;nbsp;&lt;br&gt;아래 블로그를 참고하였다.&lt;br&gt;&lt;a href=&quot;https://develoyummer.tistory.com/101&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://develoyummer.tistory.com/101&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. R&lt;/b&gt;&lt;b&gt;edis 바이너리 파일을 가져오자&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 아래 명령어들을 실행하자&lt;br&gt;&lt;b&gt;1. 레디스 압축파일 다운&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;wget https://download.redis.io/releases/redis-6.0.10.tar.gz&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;2. 레디스 압축파일 압축 풀기&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;tar -xzf redis-6.0.10.tar.gz&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;3. 압축 해제한 디렉토리로 이동&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cd redis-6.0.10&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;4. 레디스 컴파일&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;make&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;이 과정을 거치면 `redis-6.0.10/src` 경로에 `redis-server` 파일이 생길 것이다.&lt;br&gt;해당 파일을 Spring Boot 프로젝트의 `src/main/resource/binary/redis/`경로로&amp;nbsp;옮겨준다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;2. Config 파일 수정&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EmbeddedRedisConfig&lt;/b&gt;&lt;br&gt;먼저&amp;nbsp;Mac&amp;nbsp;OS인지&amp;nbsp;확인하는&amp;nbsp;isMac()&amp;nbsp;메소드를&amp;nbsp;추가해준다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private boolean isMac() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Objects.equals(System.getProperty(&quot;os.name&quot;), &quot;Mac OS X&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이제 start() 메소드에 아래 내용으로 바꿔준다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@PostConstruct
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void start() throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int port = isRedisRunning() ? findAvailablePort() : redisPort;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// redisServer = new RedisServer(port); // 기존 코드
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(isMac()){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisServer = new RedisServer(Objects.requireNonNull(getRedisFileForArcMac()), port);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}else{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisServer = new RedisServer(port);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;redisServer.start();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;친구의 도움을 많이 받았고... 결국 Redis 설치 엔딩이었지만... 그래도 Embedded Redis라는 것을 알게되었으니... 좋다.. &lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Backend/Spring</category>
      <category>redis</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/229</guid>
      <comments>https://settong.tistory.com/entry/Spring-Boot-Embedded-Redis-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0-Mac-%ED%95%B4%EA%B2%B0%EC%B1%85#entry229comment</comments>
      <pubDate>Tue, 25 Feb 2025 17:35:16 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스/level 3] 코딩 테스트 공부 - 118668 (Java)</title>
      <link>https://settong.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Javalevel-3-%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B3%B5%EB%B6%80-118668</link>
      <description>&lt;h1&gt;[level 3] 코딩 테스트 공부 - 118668&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118668?language=java&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739207984522&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;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118668?language=java&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/drpWXV/hyYciu0nXD/L4hPPQd3yoy0XSJQx8yfMK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/DRwpU/hyYcgYgD9a/u6YUpG2MH1FKTJHHDFlVA0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118668?language=java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118668?language=java&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/drpWXV/hyYciu0nXD/L4hPPQd3yoy0XSJQx8yfMK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/DRwpU/hyYcgYgD9a/u6YUpG2MH1FKTJHHDFlVA0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&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;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP를 이용해 해당 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 가능한 선택지는 3가지 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;1시간을 사용,  `alp` 1 늘리기&lt;/li&gt;
&lt;li&gt;1시간을 사용, `cop` 1 늘리기&lt;/li&gt;
&lt;li&gt;문제를 해결하여 주어진 `cost`를 사용, `alp_rwd`, `cop_rwd` 만큼 늘리기&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;row를 `alp`, col을 `cop`으로 두고 `[alp][cop]`에 시간(`cost`)을 저장하여 DP를 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 [알고력, 코딩력]에 도달하기 위한 경우의 수 중 cost가 가장 적은 것을 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 `[alp][cop]`에서&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;1시간을 사용,  `alp` 1 늘리기&lt;br /&gt;`dp[alp+1][cop]`와 `dp[alp][cop]+1`을 비교하여 작은 값을 선택한다.&lt;/li&gt;
&lt;li&gt;1시간을 사용, `cop` 1 늘리기&lt;br /&gt;`dp[alp][cop+1]`와 `dp[alp][cop]+1`을 비교하여 작은 값을 선택한다.&lt;/li&gt;
&lt;li&gt;문제를 해결하여 주어진 `cost`를 사용, `alp_rwd`, `cop_rwd` 만큼 늘리기&lt;br /&gt;`dp[alp+alp_wrd][cop+cop_rwd]`와 `dp[alp][cop]+cost`를 비교하여 작은 값을 선택한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 최소 값을 비교하여 저장해야하므로, dp 배열의 초기 값을 큰 값으로 바꿔두자!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 과정을 거친 후 주어진 문제 중 alp_req와 cop_req가 가장 클 때의 시간을 return 한다.&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;/h3&gt;
&lt;pre id=&quot;code_1739208029124&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int alp, int cop, int[][] problems) {
        int maxal = Math.max(alp, Arrays.stream(problems).mapToInt(p -&amp;gt; p[0]).max().orElse(0));
        int maxco = Math.max(cop, Arrays.stream(problems).mapToInt(p -&amp;gt; p[1]).max().orElse(0));

        int[][] dp = new int[maxal + 1][maxco + 1];
        Arrays.stream(dp).forEach(i -&amp;gt; Arrays.fill(i, 3151)); //dp배열 큰 값으로 초기화
        dp[alp][cop] = 0;  // 시작점 초기화

        for (int al = alp; al &amp;lt;= maxal; al++) {
            for (int co = cop; co &amp;lt;= maxco; co++) {
                // 한 시간씩 기다려서 alp 또는 cop 1 증가
                if (al &amp;lt; maxal) dp[al + 1][co] = Math.min(dp[al + 1][co], dp[al][co] + 1);
                if (co &amp;lt; maxco) dp[al][co + 1] = Math.min(dp[al][co + 1], dp[al][co] + 1);

                // 문제 풀었을 때 경험치 증가
                for (int[] p : problems) {
                    if (al &amp;gt;= p[0] &amp;amp;&amp;amp; co &amp;gt;= p[1]) {
                        int a = Math.min(maxal, al + p[2]);
                        int c = Math.min(maxco, co + p[3]);
                        dp[a][c] = Math.min(dp[a][c], dp[al][co] + p[4]);
                    }
                }
            }
        }

        return dp[maxal][maxco];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩 테스트 정복기/프로그래머스</category>
      <category>다이나믹프로그래밍</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/218</guid>
      <comments>https://settong.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Javalevel-3-%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B3%B5%EB%B6%80-118668#entry218comment</comments>
      <pubDate>Wed, 12 Feb 2025 09:11:49 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스/level 3] 파괴되지 않은 건물 - 92344 (+누적합, Java)</title>
      <link>https://settong.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4level-3-%ED%8C%8C%EA%B4%B4%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EA%B1%B4%EB%AC%BC-92344-%EB%88%84%EC%A0%81%ED%95%A9-Java</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/92344&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739209483680&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;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NIMih/hyYb61Zexv/MxSyjtqkSY4FlXnsX7m4HK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/H5V8t/hyYckzDoAL/S0JyS36qPVxl3n6FUZNUT1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NIMih/hyYb61Zexv/MxSyjtqkSY4FlXnsX7m4HK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/H5V8t/hyYckzDoAL/S0JyS36qPVxl3n6FUZNUT1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&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;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[level&amp;nbsp;3]&amp;nbsp;파괴되지&amp;nbsp;않은&amp;nbsp;건물&amp;nbsp;-&amp;nbsp;92344&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;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;(r1, c1)에서 (r2, c2)까지 n을 더할 때, 문제처럼 해당 과정이 k만큼 수행되어야 한다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for문으로 작업 시 r*c*k 만큼 수행해야한다. 이는 효율적이지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에, 주어진 r1, c1, r2, c2를 이용하여 더하는 구간을 표시하고 이를 더하는 누적합을 수행한다.&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;아래 이차원 배열에서 (0, 0) 부터 (3,3) 까지 5를 더한다고 하자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tLk9J/btsMdGuePfX/vQUqSXYBLb8yVkKkKrELXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tLk9J/btsMdGuePfX/vQUqSXYBLb8yVkKkKrELXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tLk9J/btsMdGuePfX/vQUqSXYBLb8yVkKkKrELXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtLk9J%2FbtsMdGuePfX%2FvQUqSXYBLb8yVkKkKrELXK%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;350&quot; height=&quot;316&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;r1 = 0, c1 = 0, r2 = 3, c2 = 3, n=5 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[r1][c1] = n&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[r1][c2+1] = -n&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[r2+1][c1] = -n&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[r2+1][c2+1] = n&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CGGfT/btsMcRiInVX/M3E0BMG5Up6gEYkQ1sJVt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CGGfT/btsMcRiInVX/M3E0BMG5Up6gEYkQ1sJVt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CGGfT/btsMcRiInVX/M3E0BMG5Up6gEYkQ1sJVt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCGGfT%2FbtsMcRiInVX%2FM3E0BMG5Up6gEYkQ1sJVt0%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;350&quot; height=&quot;319&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;319&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;[r][c] = [r][c] + [r][c-1] 을 해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/udHUY/btsMcfxJlUc/s6m3Evpe5xbtvXc50GLUL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/udHUY/btsMcfxJlUc/s6m3Evpe5xbtvXc50GLUL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/udHUY/btsMcfxJlUc/s6m3Evpe5xbtvXc50GLUL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FudHUY%2FbtsMcfxJlUc%2Fs6m3Evpe5xbtvXc50GLUL1%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;350&quot; height=&quot;315&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;862&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;[r][c] = [r][c] + [r-1][c] 을 해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RkfDe/btsMckFEfsq/khbVrauz9H6XwqgjXyXaY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RkfDe/btsMckFEfsq/khbVrauz9H6XwqgjXyXaY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RkfDe/btsMckFEfsq/khbVrauz9H6XwqgjXyXaY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRkfDe%2FbtsMckFEfsq%2FkhbVrauz9H6XwqgjXyXaY0%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;350&quot; height=&quot;315&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 활용하여 문제를 해결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://velog.io/@ich0906/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EA%B4%B4%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EA%B1%B4%EB%AC%BC-%EB%88%84%EC%A0%81%ED%95%A9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@ich0906/프로그래머스-파괴되지-않은-건물-누적합&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오테크에 해당 문제에 대한 정석 풀이가 제공되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tech.kakao.com/posts/488&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tech.kakao.com/posts/488&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739209636613&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;2022 카카오 신입 공채 1차 온라인 코딩테스트 for Tech developers 문제해설 - tech.kakao.com&quot; data-og-description=&quot;지난 2021년 9월 11일 토요일 오후 2시부터 7시까지 5시간 동안 2022 ...&quot; data-og-host=&quot;tech.kakao.com&quot; data-og-source-url=&quot;https://tech.kakao.com/posts/488&quot; data-og-url=&quot;https://tech.kakao.com/posts/488&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cewQTQ/hyYfWw27lC/bmT3ZXBM3Zr1kL59DkFDVK/img.png?width=896&amp;amp;height=429&amp;amp;face=0_0_896_429,https://scrap.kakaocdn.net/dn/sTOY9/hyYceMUwbq/OumqZnx5bppRKal2de7r7k/img.png?width=896&amp;amp;height=429&amp;amp;face=0_0_896_429,https://scrap.kakaocdn.net/dn/WhKSM/hyYcbQdB6C/KU2sHzLc4sEQcMTPNiO4S1/img.png?width=896&amp;amp;height=429&amp;amp;face=0_0_896_429&quot;&gt;&lt;a href=&quot;https://tech.kakao.com/posts/488&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tech.kakao.com/posts/488&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cewQTQ/hyYfWw27lC/bmT3ZXBM3Zr1kL59DkFDVK/img.png?width=896&amp;amp;height=429&amp;amp;face=0_0_896_429,https://scrap.kakaocdn.net/dn/sTOY9/hyYceMUwbq/OumqZnx5bppRKal2de7r7k/img.png?width=896&amp;amp;height=429&amp;amp;face=0_0_896_429,https://scrap.kakaocdn.net/dn/WhKSM/hyYcbQdB6C/KU2sHzLc4sEQcMTPNiO4S1/img.png?width=896&amp;amp;height=429&amp;amp;face=0_0_896_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;2022 카카오 신입 공채 1차 온라인 코딩테스트 for Tech developers 문제해설 - tech.kakao.com&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;지난 2021년 9월 11일 토요일 오후 2시부터 7시까지 5시간 동안 2022 ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tech.kakao.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.util.*;
class Solution {
    public int solution(int[][] board, int[][] skill) {
        int row = board.length, col = board[0].length;
        int[][] sum = new int[row][col]; 
        
        
        // 누적합 계산
        for(int[] s: skill){
            int type=s[0]==1?-1:1, r1=s[1], c1=s[2], r2=s[3], c2=s[4], degree=s[5];
            sum[r1][c1] += type*degree;
            if(c2+1&amp;lt;col)sum[r1][c2+1] += (-type)*degree;
            if(r2+1&amp;lt;row) sum[r2+1][c1] += (-type)*degree;
            if(r2+1&amp;lt;row&amp;amp;&amp;amp;c2+1&amp;lt;col) sum[r2+1][c2+1] += type*degree;
        }
        for(int r=0; r&amp;lt;row; r++){
            for(int c=0; c&amp;lt;col; c++){
                if(c&amp;gt;0) sum[r][c] += sum[r][c-1];
            }
        }
        for(int c=0; c&amp;lt;col; c++){
            for(int r=0; r&amp;lt;row; r++){
                if(r&amp;gt;0) sum[r][c] += sum[r-1][c];
            }
        }
        
        // board랑 합산
        int answer = 0;
        for(int r=0; r&amp;lt;row; r++){
            for(int c=0; c&amp;lt;col; c++){
                if(board[r][c] &amp;gt; -sum[r][c]) answer++;
            }
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩 테스트 정복기/프로그래머스</category>
      <category>누적합</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/219</guid>
      <comments>https://settong.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4level-3-%ED%8C%8C%EA%B4%B4%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EA%B1%B4%EB%AC%BC-92344-%EB%88%84%EC%A0%81%ED%95%A9-Java#entry219comment</comments>
      <pubDate>Tue, 11 Feb 2025 09:11:28 +0900</pubDate>
    </item>
    <item>
      <title>URI와 웹 브라우저 요청 흐름</title>
      <link>https://settong.tistory.com/entry/URI%EC%99%80-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9A%94%EC%B2%AD-%ED%9D%90%EB%A6%84</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;URI(Uniform Resource Identifier)&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;URI란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URI란 인터넷에서 자원을 식별하기 위한 문자열을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 상의 특정 자원(파일, 페이지, API 등)을 식별하거나 위치를 지정하는 방식이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;URI는 URL과 URN을 포함한다.&lt;br /&gt;URL: 리소스가 있는 위치(Locator)를 지정&lt;br /&gt;URN: 리소스에 이름(Name)을 부여&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URI 구성 요소&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;schema&lt;/span&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;://&lt;span style=&quot;color: #f89009;&quot;&gt;[userinfo@]&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;host&lt;/span&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;[:port]&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;[/path]&lt;/span&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;[?query]&lt;span style=&quot;color: #c0d1e7;&quot;&gt;[#fragment]&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;https&lt;/span&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;://&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;www.google.com&lt;/span&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;:443&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;/search&lt;/span&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;?q=hello&amp;amp;hl=ko&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- schema&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 프로토콜을 정의. 어떤 방식으로 자원에 접근할 것인가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- userinfo&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL에 사용자 정보를 포함해서 인증해야될 때 사용. (거의 사용 안함)&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;- host&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자원이 위치한 서버의 도메인 이름 or IP 주소&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;- port&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;HTTP 의 기본포트는 80, HTTPS의 기본포트는 443&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;- path&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 내 자원의 위치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- query&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;? 뒤에 key=value 형태로 작성하고, 여러 키-값 쌍을 &amp;amp;로 구분.&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;- fragment&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;서버에 전송하는 정보는 아니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;웹 브라우저 요청의 흐름&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1ZCjp/btsLV8LI1NW/dCOBNC8gsgjw1nzo7siHs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1ZCjp/btsLV8LI1NW/dCOBNC8gsgjw1nzo7siHs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1ZCjp/btsLV8LI1NW/dCOBNC8gsgjw1nzo7siHs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1ZCjp%2FbtsLV8LI1NW%2FdCOBNC8gsgjw1nzo7siHs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;630&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 브라우저에서 사용자가 URL을 입력.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. DNS 서버로 도메인에서 목적지 IP 주소를 찾아냄. port가 생략되어 있다면 schema 부분으로 찾아냄.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 웹 브라우저가 HTTP/HTTPS 요청 메시지를 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bExlGC/btsLW2Ylifq/tHWji1m85BNjDrjYeSGWW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bExlGC/btsLW2Ylifq/tHWji1m85BNjDrjYeSGWW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bExlGC/btsLW2Ylifq/tHWji1m85BNjDrjYeSGWW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbExlGC%2FbtsLW2Ylifq%2FtHWji1m85BNjDrjYeSGWW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;588&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Socket 라이브러리를 통해 IP와 PORT 정보를 기반으로 TCP/IP 연결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. TCP/IP 패킷 생성 및 서버에 전달.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 서버에서 클라이언트의 요청을 확인하고 응답.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 브라우저 렌더링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 출처/참고&lt;/p&gt;
&lt;figure id=&quot;og_1737551715609&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&quot; data-og-description=&quot;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-url=&quot;https://www.inflearn.com/course/http-웹-네트워크&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Computer Science/Network</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/217</guid>
      <comments>https://settong.tistory.com/entry/URI%EC%99%80-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9A%94%EC%B2%AD-%ED%9D%90%EB%A6%84#entry217comment</comments>
      <pubDate>Sat, 25 Jan 2025 09:15:29 +0900</pubDate>
    </item>
    <item>
      <title>포트(PORT)와 DNS</title>
      <link>https://settong.tistory.com/entry/PORT%EC%9D%98-%EC%97%AD%ED%95%A0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;PORT&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQKsGm/btsLVNnyLmA/Yttu2Hf2FD2CXgwoa81kb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQKsGm/btsLVNnyLmA/Yttu2Hf2FD2CXgwoa81kb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQKsGm/btsLVNnyLmA/Yttu2Hf2FD2CXgwoa81kb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQKsGm%2FbtsLVNnyLmA%2FYttu2Hf2FD2CXgwoa81kb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;204&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;클라이언트에서 게임도 하고 화상통화도 하고 웹 브라우저도 사용하고 있다면 여러개의 서버랑 통신해야한다.&lt;br /&gt;클라이언트 IP에서 온 패킷이 게임/화상통화/웹 브라우저 중 어디에서 온 패킷인지 구별하려면?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;IP 주소와 함께 사용되고, 하나의 장치에서 여러 어플리케이션이 동시에 작동할 수 있도록 돕는다.&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;즉, IP는 목적지 서버를 찾는 용도이고, 서버 안에서 돌아가는 애플리케이션을 구분하는게 PORT이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;DNS(Domain Name System)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS란 도메인 이름을 IP 주소로 변환해주는 시스템이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예: `www.google.com` &amp;rarr; `200.200.200.2`&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTecTS/btsLVHAQ1pe/DW20lSwrvqotcDKnQ8ZVlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTecTS/btsLVHAQ1pe/DW20lSwrvqotcDKnQ8ZVlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTecTS/btsLVHAQ1pe/DW20lSwrvqotcDKnQ8ZVlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTecTS%2FbtsLVHAQ1pe%2FDW20lSwrvqotcDKnQ8ZVlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;236&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;750&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;도메인을 사용하는 이유는?&lt;/b&gt;&lt;br /&gt;- 사람들이 IP주소(숫자)를 외우는 대신 기억하기 쉬운 도메인 이름(문자)를 사용.&lt;br /&gt;- 서버 IP의 주소가 바뀌더라도 도메인 이름은 변하지 않음.&lt;br /&gt;&amp;nbsp; (IP주소가 변경되어도 DNS가 이를 자동으로 관리)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 출처/참고&lt;/p&gt;
&lt;figure id=&quot;og_1737548940351&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&quot; data-og-description=&quot;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-url=&quot;https://www.inflearn.com/course/http-웹-네트워크&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Computer Science/Network</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/216</guid>
      <comments>https://settong.tistory.com/entry/PORT%EC%9D%98-%EC%97%AD%ED%95%A0#entry216comment</comments>
      <pubDate>Fri, 24 Jan 2025 08:30:14 +0900</pubDate>
    </item>
    <item>
      <title>TCP/UDP</title>
      <link>https://settong.tistory.com/entry/TCPUDP</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;TCP / UDP란?&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pQdIO/btsLV7F3iUy/C0ahJgpzPcihKo6UlcmmQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pQdIO/btsLV7F3iUy/C0ahJgpzPcihKo6UlcmmQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pQdIO/btsLV7F3iUy/C0ahJgpzPcihKo6UlcmmQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpQdIO%2FbtsLV7F3iUy%2FC0ahJgpzPcihKo6UlcmmQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;144&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP/UDP는 OSI 7 계층 모델의&lt;b&gt; 전송계층&lt;/b&gt;에서 동작하는 프로토콜.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP와 함께 사용되어 데이터를 송수신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘의 주된 차이는 &lt;b&gt;데이터 전송 방식&lt;/b&gt;과 &lt;b&gt;신뢰성&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;TCP(전송 제어 프로토콜, Transmission Control Protocol)의 특징&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 연결지향 : 3 way Handsahke&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP의 논리적 연결 과정을 말한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bClwZv/btsLVZON5rX/KfAKDmKAzEZKTWLUb96QMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bClwZv/btsLVZON5rX/KfAKDmKAzEZKTWLUb96QMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bClwZv/btsLVZON5rX/KfAKDmKAzEZKTWLUb96QMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbClwZv%2FbtsLVZON5rX%2FKfAKDmKAzEZKTWLUb96QMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;168&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* SYN : 접속 요청 / ACK : 요청 수락(ACK와 함께 데이터 전송 가능)&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 클라이언트가 서버의 요청을 수락함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 신뢰성 : 순서 보장&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, TCP 프로토콜을 이용한 메시지 전달 과정을 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPtXHe/btsLWZHhwp7/7DsF806v0GNRzGgJS09Q91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPtXHe/btsLWZHhwp7/7DsF806v0GNRzGgJS09Q91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPtXHe/btsLWZHhwp7/7DsF806v0GNRzGgJS09Q91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPtXHe%2FbtsLWZHhwp7%2F7DsF806v0GNRzGgJS09Q91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;290&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;HTTP:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;프로그램이 메시지 생성, socket 라이브러리를 통해 전달.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;TCP:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;TCP 정보 생성, 메시지 데이터 포함.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;IP&lt;/b&gt;: IP 패킷 생성, TCP 세그먼트 포함.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr;즉, IP 패킷은 TCP 세그먼트를, TCP세그먼트는 메시지 데이터를 포함하고 있음.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWzOOQ/btsLWY2IAMn/HVUL3TCfVNYlCbGOoe8b80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWzOOQ/btsLWY2IAMn/HVUL3TCfVNYlCbGOoe8b80/img.png&quot; data-alt=&quot;TCP/IP 패킷 구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWzOOQ/btsLWY2IAMn/HVUL3TCfVNYlCbGOoe8b80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWzOOQ%2FbtsLWY2IAMn%2FHVUL3TCfVNYlCbGOoe8b80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;231&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;TCP/IP 패킷 구성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;TCP 세그먼트는 출발지/목적지 PORT, 전송 제어, 순서, 검증 정보 등을 포함함.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;912&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rXhTu/btsLXUMfkXV/2KTKmFpgBKBqCTPumDd2B0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rXhTu/btsLXUMfkXV/2KTKmFpgBKBqCTPumDd2B0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rXhTu/btsLXUMfkXV/2KTKmFpgBKBqCTPumDd2B0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrXhTu%2FbtsLXUMfkXV%2F2KTKmFpgBKBqCTPumDd2B0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;166&quot; data-origin-width=&quot;912&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 세그먼트에 순서에 대한 정보를 포함하기 때문에 잘못된 순서로 패킷이 전달되면 이를 최적화 할 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에, IP 프로토콜로는 해결되지 않던 순서, 제어 등의 문제를 해결.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;UDP(사용자 데이터그램 프로토콜, User Datagram Protocol)특징&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 비연결형&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 신뢰성 보장 X / 오류검출 O&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 빠른 데이터 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP와 거의 같다. PORT와 체크섬 정도만 추가된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 출처/참고&lt;/p&gt;
&lt;figure id=&quot;og_1737548911983&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&quot; data-og-description=&quot;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-url=&quot;https://www.inflearn.com/course/http-웹-네트워크&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Computer Science/Network</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/215</guid>
      <comments>https://settong.tistory.com/entry/TCPUDP#entry215comment</comments>
      <pubDate>Thu, 23 Jan 2025 08:58:39 +0900</pubDate>
    </item>
    <item>
      <title>IP(인터넷 프로토콜)</title>
      <link>https://settong.tistory.com/entry/IP%EC%9D%B8%ED%84%B0%EB%84%B7-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;IP(인터넷 프로토콜, Internet Protocol) 란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP는 인터넷에서 &lt;b&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;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;OSI 7 계층 모델의 &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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;역할&lt;/b&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 주소로 데이터를 전달.&lt;/li&gt;
&lt;li&gt;패킷 단위로 데이터를 전달.&lt;/li&gt;
&lt;li&gt;네트워크 계층에서 host의 주소 지정과 패킷 분할/조립을 담당.&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;b&gt;패킷 전달 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 패킷 구성하기&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/viN9h/btsLV34Fy9J/EzPdlABdhKWShifkDGLETK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/viN9h/btsLV34Fy9J/EzPdlABdhKWShifkDGLETK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/viN9h/btsLV34Fy9J/EzPdlABdhKWShifkDGLETK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FviN9h%2FbtsLV34Fy9J%2FEzPdlABdhKWShifkDGLETK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;235&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출발지 IP와 목적지 IP, 전송 데이터 등을 담은 패킷을 구성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 IP 프로토콜에 의해 서버들이 규약을 따르고 있다.&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;2. 클라이언트 패킷 전달&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHBGtW/btsLW4aJjql/5smrIxHWKnZKWzAxv7zb9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHBGtW/btsLW4aJjql/5smrIxHWKnZKWzAxv7zb9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHBGtW/btsLW4aJjql/5smrIxHWKnZKWzAxv7zb9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHBGtW%2FbtsLW4aJjql%2F5smrIxHWKnZKWzAxv7zb9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;202&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패킷을 통해 인터넷 망에서 노드들이 출발지/목적지를 확인하고 목적지 IP(200.200.200.2)까지 전달한다.&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;3. 서버 패킷 전달&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;625&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bujc57/btsLV9cNRdr/UTdqWvzh7hREjmoDankfB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bujc57/btsLV9cNRdr/UTdqWvzh7hREjmoDankfB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bujc57/btsLV9cNRdr/UTdqWvzh7hREjmoDankfB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbujc57%2FbtsLV9cNRdr%2FUTdqWvzh7hREjmoDankfB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;195&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;625&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;IP 프로토콜의 한계&lt;/b&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;br /&gt;&lt;/b&gt;대상 서버가 패킷을 받을수 있는 상태인지 모름.&lt;br /&gt;패킷을 받을 대상이 없거나 서비스 불능이여도 패킷 전송함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비신뢰성&lt;br /&gt;&lt;/b&gt;순서 보장 X&lt;br /&gt;손실 가능성 있음.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로그램 구분&lt;br /&gt;&lt;/b&gt;같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이면 구분 불가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이런 문제를 해결하기 위해 TCP 프로토콜 사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 출처/참고&lt;/p&gt;
&lt;figure id=&quot;og_1737546656392&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&quot; data-og-description=&quot;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-url=&quot;https://www.inflearn.com/course/http-웹-네트워크&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yQOxd/hyX4pHo1Vb/Cij4ZIEcyASyp8gkgp5yd1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/chjbyh/hyX4sjPtED/Dl0UT09a2bkRm4whPyK8R0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BDTsm/hyX4yRSf7u/jSrt4mTZskZy9w9AWylpik/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 강의 | 김영한 - 인프런&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;김영한 | 실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., [사진]   확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 세 번째 강의입니다. 우아한형제들 최연&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Computer Science/Network</category>
      <author>settong</author>
      <guid isPermaLink="true">https://settong.tistory.com/214</guid>
      <comments>https://settong.tistory.com/entry/IP%EC%9D%B8%ED%84%B0%EB%84%B7-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C#entry214comment</comments>
      <pubDate>Wed, 22 Jan 2025 20:51:47 +0900</pubDate>
    </item>
  </channel>
</rss>