<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>나만의 개발블로그</title>
    <link>https://hminor.tistory.com/</link>
    <description>나도 개발자..?</description>
    <language>ko</language>
    <pubDate>Fri, 10 Apr 2026 09:36:44 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>hminor</managingEditor>
    <image>
      <title>나만의 개발블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/6361502/attach/3b14506dfd774917add0547b6e740a9d</url>
      <link>https://hminor.tistory.com</link>
    </image>
    <item>
      <title>[ 노트 ] NextJS - TanStack Query 적용 이해</title>
      <link>https://hminor.tistory.com/611</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Q1.&amp;nbsp;기존&amp;nbsp;service에서&amp;nbsp;domainService&amp;nbsp;메서드를&amp;nbsp;추가한&amp;nbsp;이유는&amp;nbsp;해당&amp;nbsp;key값인&amp;nbsp;&amp;nbsp;api가&amp;nbsp;없다면&amp;nbsp;별도의&amp;nbsp;error&amp;nbsp;문구를&amp;nbsp;던지기&amp;nbsp;위해서&amp;nbsp;작성했는데&amp;nbsp;이렇게&amp;nbsp;하지&amp;nbsp;않으면&amp;nbsp;어떤식으로&amp;nbsp;controller에서&amp;nbsp;error를&amp;nbsp;던질&amp;nbsp;수&amp;nbsp;있어? &lt;br /&gt;&lt;br /&gt;A1.&amp;nbsp;controller&amp;nbsp;단에서&amp;nbsp;개별&amp;nbsp;함수(훅)으로&amp;nbsp;만들어서&amp;nbsp;각각&amp;nbsp;export하면&amp;nbsp;내보낼&amp;nbsp;당시&amp;nbsp;없는&amp;nbsp;메서드의&amp;nbsp;경우&amp;nbsp;에러가&amp;nbsp;발생하게&amp;nbsp;되니&amp;nbsp;해결되며,&amp;nbsp;react/nextjs&amp;nbsp;생태계의&amp;nbsp;표준&amp;nbsp;모범에&amp;nbsp;부합. &lt;br /&gt;&lt;br /&gt;Q2.&amp;nbsp;서버&amp;nbsp;컴포넌트용&amp;nbsp;API라는&amp;nbsp;건&amp;nbsp;별도의&amp;nbsp;유저&amp;nbsp;조작없이&amp;nbsp;특정&amp;nbsp;페이지&amp;nbsp;접속시&amp;nbsp;보이는&amp;nbsp;데이터로&amp;nbsp;예를&amp;nbsp;들자면&amp;nbsp;쇼핑몰&amp;nbsp;페이지에서&amp;nbsp;추천&amp;nbsp;상품&amp;nbsp;목록이&amp;nbsp;아닌&amp;nbsp;일반적인&amp;nbsp;것으로&amp;nbsp;의류&amp;nbsp;중&amp;nbsp;상의&amp;nbsp;탭을&amp;nbsp;클릭하면&amp;nbsp;누구에게나&amp;nbsp;공통으로&amp;nbsp;보일&amp;nbsp;데이터의&amp;nbsp;경우엔&amp;nbsp;서버&amp;nbsp;컴포넌트용&amp;nbsp;APi를&amp;nbsp;제작해서&amp;nbsp;fetch하여&amp;nbsp;페이지&amp;nbsp;로드&amp;nbsp;시&amp;nbsp;서버에서&amp;nbsp;데이터를&amp;nbsp;가져와서&amp;nbsp;바로&amp;nbsp;보일&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;하면&amp;nbsp;좋겠다는거야? &lt;br /&gt;&lt;br /&gt;A2.&amp;nbsp;ㅇㅇ&amp;nbsp;맞음,&amp;nbsp;누구에게나&amp;nbsp;공통으로&amp;nbsp;보일&amp;nbsp;데이터인&amp;nbsp;&quot;페이지의&amp;nbsp;핵심이&amp;nbsp;되는&amp;nbsp;초기&amp;nbsp;콘텐츠&quot;는&amp;nbsp;서버&amp;nbsp;컴포넌트에서&amp;nbsp;fetch로&amp;nbsp;처리,&amp;nbsp;초기&amp;nbsp;콘텐츠&amp;nbsp;위에서&amp;nbsp;일어나는&amp;nbsp;사용자&amp;nbsp;동적인&amp;nbsp;상호작용은&amp;nbsp;클라이언트&amp;nbsp;컴포넌트와&amp;nbsp;TanStack&amp;nbsp;Query가&amp;nbsp;담당. &lt;br /&gt;&lt;br /&gt;Q2-1.&amp;nbsp;fetch와&amp;nbsp;TanStack&amp;nbsp;Query&amp;nbsp;모두&amp;nbsp;사용하는&amp;nbsp;즉,&amp;nbsp;서버&amp;nbsp;컴포넌트와&amp;nbsp;클라이언트&amp;nbsp;컴포넌트&amp;nbsp;둘다&amp;nbsp;처리가&amp;nbsp;필요하다면&amp;nbsp;같은&amp;nbsp;api&amp;nbsp;작성을&amp;nbsp;2번해야하는데&amp;nbsp;이는&amp;nbsp;어떤식으로&amp;nbsp;관리해야&amp;nbsp;효율적일까? &lt;br /&gt;&lt;br /&gt;A2-1.&amp;nbsp;실제&amp;nbsp;API&amp;nbsp;요청&amp;nbsp;로직은&amp;nbsp;한&amp;nbsp;번만&amp;nbsp;작성하고,&amp;nbsp;해당&amp;nbsp;로직을&amp;nbsp;서버&amp;nbsp;컴포넌트와&amp;nbsp;TanStack&amp;nbsp;Query에서&amp;nbsp;가져다&amp;nbsp;사용하기.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1c1e; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Step 1: 순수 API 함수 계층 만들기&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1c1e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #e4e4e2; color: #32302c;&quot;&gt;services/domains.ts&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(새로운 단일 API 계층)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1765177528239&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이 파일은 React와 무관한 순수 TypeScript/JavaScript 파일입니다.

// 1. 파라미터를 받아 URL을 만들고, fetch를 호출하고, 결과를 반환하는 핵심 로직
async function fetchDomainList(params) {
  const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080';
  const queryString = new URLSearchParams(params).toString();
  const url = `${API_BASE_URL}/api/domain/get/list?${queryString}`;

  // Next.js의 확장된 fetch를 사용합니다.
  const response = await fetch(url, {
    // 서버 컴포넌트에서 이 함수를 호출할 때 캐시 전략을 정할 수 있습니다.
    // 클라이언트에서는 이 옵션이 무시됩니다.
    cache: 'no-store', 
  });

  if (!response.ok) {
    // 에러 처리는 여기서 일관되게 할 수 있습니다.
    throw new Error('도메인 목록을 가져오는데 실패했습니다.');
  }

  return response.json(); // Promise&amp;lt;Data&amp;gt;를 반환합니다.
}

// 필요하다면 다른 API 함수들도 이런 식으로 만듭니다.
async function fetchDomainDetail(id) {
  // ...
}

// 2. 작성한 함수들을 export 합니다.
export const domainAPI = {
  getList: fetchDomainList,
  getDetail: fetchDomainDetail,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1c1e; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Step 2: 서버 컴포넌트에서 이 함수를 직접 사용하기&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1c1e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #e4e4e2; color: #32302c;&quot;&gt;app/domains/page.tsx&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(서버 컴포넌트)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1765177536846&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { domainAPI } from '@/services/domains'; // Step 1에서 만든 함수를 import

export default async function DomainsPage() {
  // 서버에서 페이지를 렌더링하기 전에 데이터를 직접 호출하고 기다립니다.
  const initialDomains = await domainAPI.getList({ page: 1, limit: 10 });

  return (
    &amp;lt;main&amp;gt;
      &amp;lt;h1&amp;gt;도메인 목록 (초기 데이터는 서버 렌더링)&amp;lt;/h1&amp;gt;
      {/* 
        이 초기 데이터를 클라이언트 컴포넌트에 넘겨주어
        클라이언트에서의 추가적인 상호작용을 처리하게 합니다.
      */}
      &amp;lt;DomainListClient initialData={initialDomains} /&amp;gt;
    &amp;lt;/main&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1c1e; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Step 3: TanStack Query 훅(Controller)에서 이 함수를 재사용하기&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1c1e; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #e4e4e2; color: #32302c;&quot;&gt;controllers/domainController.ts&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(기존 Controller 수정)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1765177548695&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { domainAPI } from '@/services/domains'; // Step 1에서 만든 함수를 import

export const useFetchDomain = (params) =&amp;gt; {
  return useQuery({
    queryKey: ['domainList', params],
    // ✅ 핵심: 실제 API 호출 로직을 재사용합니다.
    queryFn: () =&amp;gt; domainAPI.getList(params),
    enabled: !!params,
    staleTime: 1000 * 60 * 5, // 5분
  });
};

// Mutation을 위한 래퍼 훅도 동일한 원리로 만들 수 있습니다.
// export const useUpdateDomain = ...```
이제 `useFetchDomain` 훅은 TanStack Query의 캐싱, 상태관리 등의 기능만 담당하는 **&quot;래퍼(Wrapper)&quot;**가 되고, 핵심 API 로직은 `services/domains.ts`에 위임됩니다.

---

#### Step 4: 클라이언트 컴포넌트에서 완성하기 (하이브리드 패턴)

서버 컴포넌트로부터 초기 데이터를 받고, 이후의 상호작용은 TanStack Query 훅을 사용하는 클라이언트 컴포넌트를 만듭니다.

**`components/DomainListClient.tsx` (클라이언트 컴포넌트)**
```tsx
'use client';

import { useState } from 'react';
import { useFetchDomain } from '@/controllers/domainController';

export default function DomainListClient({ initialData }) {
  const [page, setPage] = useState(1);
  const [filters, setFilters] = useState({});

  // TanStack Query 훅을 사용합니다.
  const { data, isLoading } = useFetchDomain(
    // 현재 페이지와 필터 상태를 파라미터로 전달
    { page, ...filters },
    {
      // ✅ 최적화: 서버에서 받아온 초기 데이터가 있으므로, 첫 렌더링 시에는 API를 다시 호출하지 않습니다.
      initialData: initialData,
    }
  );
  
  // ... 필터링, 페이지네이션 등 UI 로직 ...
  const handleFilterChange = () =&amp;gt; { /* setFilters(...) */ };
  const handleNextPage = () =&amp;gt; setPage(p =&amp;gt; p + 1);

  return (
    &amp;lt;div&amp;gt;
      {/* 필터 UI */}
      {/* ... */}
      
      {isLoading &amp;amp;&amp;amp; &amp;lt;p&amp;gt;데이터 갱신 중...&amp;lt;/p&amp;gt;}
      
      &amp;lt;ul&amp;gt;
        {data?.items.map((domain) =&amp;gt; (
          &amp;lt;li key={domain.id}&amp;gt;{domain.name}&amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;

      &amp;lt;button onClick={handleNextPage}&amp;gt;다음 페이지&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>노트</category>
      <category>Nextjs</category>
      <category>Tanstack Query</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/611</guid>
      <comments>https://hminor.tistory.com/611#entry611comment</comments>
      <pubDate>Mon, 8 Dec 2025 16:06:56 +0900</pubDate>
    </item>
    <item>
      <title>Docker&amp;amp;Container - Docker로 MySQL 구동하기</title>
      <link>https://hminor.tistory.com/610</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&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;p data-ke-size=&quot;size16&quot;&gt;개발자 유미님의 영상을 보고 Docker로 MySQL을 구동하는 방법에 대해 알게 되어 포스팅하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법은 아주 간단하며 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, docker 설치 후 상단 검색창에 mysql 검색 후 Run&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Optional settings 내 Container name을 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Host port 입력 (상단 것만 입력했음, ex. 3306)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Environment variables에 필요한 값 추가 후 Run 클릭하여 생성&lt;br /&gt;- MYSQL_DATABASE: 생성할 데이터베이스 이름&lt;br /&gt;- MYSQL_USER: MYSQL_DATABASE에 모든 권한을 가질 새로운 사용자의 이름&lt;br /&gt;- MYSQL_PASSWORD (필수) : MYSQL_USER의 비밀번호 지정&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Spring의 경우 application.properties에 하단의 값 추가하면 사용 가능&lt;/p&gt;
&lt;pre id=&quot;code_1765005214945&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# MySQL DB connection
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://:3306/디비명?useSSL=false&amp;amp;useUnicode=true&amp;amp;serverTimezone=Asia/Seoul&amp;amp;allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=

# JPA ddl, Naming and log
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.show-sql=true&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Docker&amp;amp;Container</category>
      <category>docker</category>
      <category>mysql</category>
      <category>개발자유미</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/610</guid>
      <comments>https://hminor.tistory.com/610#entry610comment</comments>
      <pubDate>Sat, 6 Dec 2025 16:23:02 +0900</pubDate>
    </item>
    <item>
      <title>[백준, 자바, 14500번] 테트로미노</title>
      <link>https://hminor.tistory.com/609</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;h2 style=&quot;color: #585f69; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;해당 문제는 어떻게 푸는 방법이 좋을지 고민했을 때&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;각 도형에 따른 변형을 최소화하면서, 기준 좌표로부터&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이동가능한 좌표 탐색을 4방향을 우선적으로 작성 후 값을 도출하는 것이 좋을 것 같다고 판단.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;다만, 이러한 노가다가 과연 적절한지 고민해봤는데 나쁘지 않을 듯해서 아래와 같이 작성&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그리고 무슨 5중 for문으로 해결한 문제는 이번이 처음인듯...&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그래도 최대한 코드를 가독성 좋으며, 구조적으로 작성하려고 노력하여 아래와 같이 작성.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;문제 자체는 크게 어려운 건 아니지만, 번거로웠다? 정도였음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class _14500 {
    static BufferedReader br;
    static StringTokenizer st;
    static int[][][][] li;
    static int[][] mtx;
    static int N;
    static int M;
    static int result = 0;
    public static void main(String[] args) throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        li = new int[5][][][];
        addDefault();
        findTetro();
        System.out.println(result);
    }

    private static void addDefault() throws IOException {
        li[0] = new int[][][] {
                {{0, 0}, {0, 1}, {0, 2}, {0, 3}},
                {{0, 0}, {1, 0}, {2, 0}, {3, 0}}
        };
        li[1] = new int[][][] {
                {{0, 0}, {0, 1}, {1, 1}, {1, 0}}
        };
        li[2] = new int[][][] {
                {{0, -1}, {0, 0}, {0, 1}, {1, 0}},
                {{0, -1}, {0, 0}, {-1, 0}, {1, 0}},
                {{0, -1}, {0, 0}, {-1, 0}, {0, 1}},
                {{-1, 0}, {0, 0}, {0, 1}, {1, 0}}
        };
        li[3] = new int[][][] {
                {{0, 0}, {1, 0}, {1, 1}, {2, 1}},
                {{0, 0}, {1, 0}, {1, -1}, {2, -1}},
                {{0, 0}, {0, 1}, {-1, 1}, {-1, 2}},
                {{0, 0}, {0, 1}, {1, 1}, {1, 2}}
        };
        li[4] = new int[][][] {
                {{0, 0}, {1, 0}, {2, 0}, {2, 1}},
                {{0, 0}, {1, 0}, {2, 0}, {2, -1}},
                {{0, 0}, {1, 0}, {0, 1}, {0, 2}},
                {{0, 0}, {1, 0}, {0, -1}, {0, -2}},
                {{0, 0}, {0, 1}, {1, 1}, {2, 1}},
                {{0, 0}, {0, -1}, {1, -1}, {2, -1}},
                {{0, 0}, {-1, 0}, {0, -1}, {0, -2}},
                {{0, 0}, {-1, 0}, {0, 1}, {0, 2}}
        };

        mtx = new int[N][M];
        for (int i=0; i&amp;lt;N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j=0; j&amp;lt;M; j++) mtx[i][j] = Integer.parseInt(st.nextToken());
        }
    }

    private static void findTetro() {
        for (int i=0; i&amp;lt;N; i++) {
            for (int j=0; j&amp;lt;M; j++) {
                detailTetro(i,j);
            }
        }
    }

    private static void detailTetro(int i, int j) {
        for (int t=0; t&amp;lt;5; t++) { // 각 도형
            for (int x=0; x&amp;lt;li[t].length; x++) { // 도형 별 회전&amp;amp;대칭
                boolean state = true;
                int hap = 0;
                for (int y=0; y&amp;lt;4; y++) {
                    if ((0&amp;lt;=i+li[t][x][y][0]&amp;amp;&amp;amp;i+li[t][x][y][0]&amp;lt;N)&amp;amp;&amp;amp;(0&amp;lt;=j+li[t][x][y][1]&amp;amp;&amp;amp;j+li[t][x][y][1]&amp;lt;M)) hap+=mtx[i+li[t][x][y][0]][j+li[t][x][y][1]];
                    else {
                        state = false;
                        break;
                    }
                }
                if (state&amp;amp;&amp;amp;hap&amp;gt;result) result = hap;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;005&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/005.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/005.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <category>14500번</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자바</category>
      <category>테트로미노</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/609</guid>
      <comments>https://hminor.tistory.com/609#entry609comment</comments>
      <pubDate>Mon, 16 Dec 2024 16:02:39 +0900</pubDate>
    </item>
    <item>
      <title>Docker&amp;amp;Container - Network 2. 컨테이너간 통신</title>
      <link>https://hminor.tistory.com/608</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너간 통신&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;터미널
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker network create 작명&lt;/li&gt;
&lt;li&gt;ex) docker network create mynet1&lt;/li&gt;
&lt;li&gt;명령어
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker network: 모든 명령어 조회&lt;/li&gt;
&lt;li&gt;docker network ls: 실행 중인 네트워크&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;터미널에 컨테이너 넣기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 중인 컨테이너를 넣는 방법도 있지만&lt;/li&gt;
&lt;li&gt;이미지 생성 시 해당 네트워크에 바로 넣는 방법을 배우고자 함 (더 편리)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;터미널
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker run -d -p 포트 &amp;mdash;network 네트워크 &amp;mdash;name 작명 실행이미지:태그&lt;/li&gt;
&lt;li&gt;ex) docker run -d -p 80:80 &amp;mdash;network mynet1 &amp;mdash;name nginx-container nginx:1 (nginx)&lt;/li&gt;
&lt;li&gt;ex) docker run -d -p 8080:8080 &amp;mdash;network mynet1 &amp;mdash;name server-container nodeserver:v1 (server)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;입력하게 되면 두 개의 컨테이너가 생성되고
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 컨테이너 클릭 후 inspect에 들어가서 Networks에 들어가면
&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서로 다른 컨테이너 간 통신 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 nginx의 가상 주소는 172.18.0.2 이고&lt;/li&gt;
&lt;li&gt;server의 가상 주소는 172.18.0.3 이기에&lt;/li&gt;
&lt;li&gt;nginx에서 server로 접속 가능한 지 확인해보기 (172.18.0.3로 접속해보기)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nginx 컨테이너에서 Exec에서 아래와 같이 코드 작성해보기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;curl 172.18.0.3:8080
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;숫자로 접속하기 번거롭고 어렵다면 &amp;mdash;name으로 작성한 것으로 접속 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DNS 기능이 내부적으로 작동되고 있기에 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;axapta&quot;&gt;&lt;code&gt;curl server-container:8080
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그리고 좀 더 정확하게 입력을 하고자면, network 이름도 함께 작성하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;axapta&quot;&gt;&lt;code&gt;curl server-container.mynet:8080
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다만
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여전히 nginx 서버(컨테이너1,80)로 접속 하더라도, server(컨테이너2,8080)으로 전달이 안됨&lt;/li&gt;
&lt;li&gt;이유는 myconfig1.conf에 그냥 localhost:8080으로 이동하라고만 입력했기에&lt;/li&gt;
&lt;li&gt;그래서 웹서버컨테이너IP:8080으로 보내라고 코드 수정하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또는 DNS으로 &amp;mdash;name으로 작성한 컨테이너 이름으로 하기&lt;/li&gt;
&lt;li&gt;config를 수정 후 터미널에서 다시 아래 명령어를 입력하여 다시 빌드하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;docker build -t nginx:1 ./nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 해석(잊어버려서)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;./nginx 폴더에 있는 dockerfile을 빌드&lt;/li&gt;
&lt;li&gt;-t는 태그를 옵션으로 작성할 것이다는 의미&lt;/li&gt;
&lt;li&gt;그래서 nginx이름으로 태그를 1로 설정하여 빌드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;여기서 중요한 것은 컨테이너를 실행할 때(run)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;웹 서버가 실행된 이후 서버를 실행하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;또한 기존 실행 코드는 다음과 같이 수정할 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왜냐하면 이젠 nginx를 실행하면 웹서버로 이동하도록 설정했기 때문.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// 기존
docker run -d -p 8080:8080 --network mynet1 --name server-container n
odeserver:v1

docker run -d -p 80:80 --network mynet1 --name nginx-container nginx:
1

// 변경
docker run -d --network mynet1 --name server-container nodeserver:v1

docker run -d -p 80:80 --network mynet1 --name nginx-container nginx:1
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그리고
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크를 생성하게 되면 모드가 bridge가 기본적으로 설정되어짐&lt;/li&gt;
&lt;li&gt;이를 host 모드로 변경하면, 나의 실제 컴퓨터 자원을 사용할 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다만 일반적으로 굳이 이렇게까지 변경할 필요는 없다고 함.&lt;/li&gt;
&lt;li&gt;그리고 변경하게 되면 보안적으로 더욱 유의해야함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;005&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/005.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/005.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Docker&amp;amp;Container</category>
      <category>docker</category>
      <category>network</category>
      <category>컨테이너 통신</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/608</guid>
      <comments>https://hminor.tistory.com/608#entry608comment</comments>
      <pubDate>Sun, 15 Dec 2024 12:30:51 +0900</pubDate>
    </item>
    <item>
      <title>Docker&amp;amp;Container - Network 1. nginx 만들기</title>
      <link>https://hminor.tistory.com/607</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nginx 만들기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너 간 통신하는 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Reverse Proxy
&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;Web Server와 함께 사용할 것임&lt;/li&gt;
&lt;li&gt;순서
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 Reverse Proxy로 들어오게 되면&lt;/li&gt;
&lt;li&gt;Reverse Proxy가 Web Server로 안내&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용 이유(장점)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 정보를 숨길 수 있음&lt;/li&gt;
&lt;li&gt;https 인증서 설치가 쉬움&lt;/li&gt;
&lt;li&gt;로드밸런싱 가능&lt;/li&gt;
&lt;li&gt;로그 남기기&lt;/li&gt;
&lt;li&gt;IP차단&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;caddy&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nginx 로컬 설치 및 셋팅
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NginX 실행 순서
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Nginx 설치
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도커를 사용할 것이기에 우선 패스&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nginx 설정 파일 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker 폴더에 폴더와 파일 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) nginx/myconfig1.conf&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후 nginx 문법에 맞게 설정 코드를 작성해야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다만 따로 배운 적이 없기에 아래와 같이 우선 작성&lt;/li&gt;
&lt;li&gt;간단히 설명하자면
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;listen 80 &amp;larr; 80 포트로 들어오면&lt;/li&gt;
&lt;li&gt;location &amp;larr; 해당 코드를 실행해라는 의미
&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;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt; 여기로 보내기&lt;/li&gt;
&lt;li&gt;아래 코드는 웹서버에 도움되는 유저의 부가 정보 채워서 보내라는 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;server {
        listen 80;
        location / {
            proxy_pass &amp;lt;http://localhost:8080&amp;gt;;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리눅스의 경우엔
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/nginx/conf.d 폴더에 해당 파일을 넣으면 된다고 함&lt;/li&gt;
&lt;li&gt;그리고 기존 폴더에 default.conf 파일이 있는데
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우선 순위가 기존 파일이 더 높기에&lt;/li&gt;
&lt;li&gt;삭제 후 새롭게 작성한 파일을 넣으면 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후 nginx -g daemon off; 를 터미널에 입력하면 nginx 실행됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nginx 실행 명령어 입력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;코드 작성하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성한 nginx 폴더에 Dockerfile 만들기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후 해당 파일에 아래와 코드 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 설명
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FROM docker에서 nginx 이미지 불러오기&lt;/li&gt;
&lt;li&gt;COPY로 우리가 만든 myconfig1.conf 를 특정 경로로 옮기기&lt;/li&gt;
&lt;li&gt;기존 conf 파일을 지우기 위해 RUN 사용&lt;/li&gt;
&lt;li&gt;EXPOSE로 특정 포트 열기&lt;/li&gt;
&lt;li&gt;CMD로 실행 명령어 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 설명
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nginx
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Nginx 웹 서버 실행 명령어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;-g
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;글로벌 설정으로, 뒤에 오는 설정은 모든 Nginx 설정 파일에 영향을 미침&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;daemon off;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Nginx는 기본적으로 데몬 모드(백그라운드 실행)으로 동작&lt;/li&gt;
&lt;li&gt;Docker 컨테이너는 포그라운드에서 실행되는 프로세스를 필요로 하기에, daemon off; 를 설정하여 데몬 모드로 전환되지 않고, 포그라운드에서 실행되도록 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포그라운드 프로세스란?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 사용자의 터미널(콘솔)과 직접 연결된 상태에서 실행되는 프로세스를 의미&lt;/li&gt;
&lt;li&gt;즉, 실행 결과가 즉시 화면에 출력됨.&lt;/li&gt;
&lt;li&gt;프로세스가 종료될 때까지 터미널 제어권을 유지&lt;/li&gt;
&lt;li&gt;예를 들어, 터미널에서 실행한 명령어가 작업을 마칠 때까지 기다리는 상태.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;기존 데몬 모드(백그라운드 프로세스)란?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 터미널과 분리된 상태로 실행되는 프로세스&lt;/li&gt;
&lt;li&gt;즉, 실행 결과는 화면에 출력X, 로그도 별도 저장&lt;/li&gt;
&lt;li&gt;프로세스가 독립적으로 실행되며, 사용자는 터미널 다른 작업을 할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;쉽게 이해하자면, 데몬 모드로 실행하면 컨테이너가 실행 중단된 것으로 간주되기에, 컨테이너가 바로 종료됨.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이렇게 하면 Dcoker가 Nginx 프로세스를 주 프로세스로 인식하고, 컨테이너가 종료되지 않으며 정상적으로 동작.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;FROM nginx:1.27.2-alpine

COPY ./myconfig1.conf /etc/nginx/conf.d/myconfig1.conf
RUN rm /etc/nginx/conf.d/default.conf

EXPOSE 80
CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실행하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;터미널에서 이미지 만들기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker build -t nginx:1 ./nginx&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;생성한 nginx 이미지 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;option에서 Host port를 80 으로 변경 후 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후 이전 생성한 nodeserver인 web server를 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;option에서 Host port를 myconfig1.conf에서 설정한 것처럼 8080으로 변경 후 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다만 nginx 서버에서 80 포트로 접속하면
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nodeserver 서버인 8080 포트로 안내가 되어야 하는데 안됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이유?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 나의 컴퓨터(Host)에선 아래와 같이 2개의 가상 컴퓨터가 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상 컴퓨터1(nginx, 80)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://localhost:80&quot;&gt;localhost:80&lt;/a&gt; &amp;rarr; &lt;a href=&quot;http://localhost:8080&quot;&gt;localhost:8080&lt;/a&gt; 안내하라고 되어 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;가상 컴퓨터2(nodeserver, 8080)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다만
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상 컴퓨터1에는
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;8080 포트도 뚫려있지 않고&lt;/li&gt;
&lt;li&gt;8080 포트에서 실행중인 서버도 없기에 동작을 안함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;가상 컴퓨터2에 뚫려 있고, 실행중인 8080서버와는 완전히 구분된 별도의 컴퓨터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;해결 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상 컴퓨터1(nginx, 80)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://localhost:80&quot;&gt;localhost:80&lt;/a&gt; &amp;rarr; 가상 컴퓨터2의 &lt;a href=&quot;http://localhost:8080&quot;&gt;localhost:8080&lt;/a&gt; 안내하라고 되어야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;안전하며, 간단한 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;network&lt;/b&gt; 내에 컨테이너를 넣으면 가상 IP 주소를 부여함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따라서 가상 컴퓨터1,2 를 함께 넣어서 관리&lt;/li&gt;
&lt;li&gt;같은 네트워크 내에선
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상 IP주소가 생기기에 가상 컴퓨터끼리 통신이 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;005&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/005.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/005.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Docker&amp;amp;Container</category>
      <category>docker</category>
      <category>network</category>
      <category>Nginx</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/607</guid>
      <comments>https://hminor.tistory.com/607#entry607comment</comments>
      <pubDate>Sat, 14 Dec 2024 23:27:14 +0900</pubDate>
    </item>
    <item>
      <title>[백준, 자바, 1551번] 수열의 변화</title>
      <link>https://hminor.tistory.com/606</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;h2 style=&quot;color: #585f69; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;오늘은 간단하게 하나 풀기로 함&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;우선 해당 문제는 단순히 수열이 주어질 때&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;특정 인덱스를 앞 인덱스 값에서 뺀 값을 구하는 수를 구하는 문제이며&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;M번 반복하게 되면 결과로 나오는 값의 개수는&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;기존 N의 길이에서 N-M개로 줄어들기에 그것을 유념하여 풀어야 함&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;또한 결과를 출력 시 ,를 기준으로 출력을 하는 것으로 해결하는 것으로&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;다음과 같이 해결.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

public class _1551 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static List&amp;lt;Integer&amp;gt; li = new ArrayList&amp;lt;&amp;gt;();
    public static void main(String[] args) throws IOException {

        st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        addData(N);
        findResult(N,M);
        System.out.println(li.stream().map(String::valueOf).collect(Collectors.joining(&quot;,&quot;)));
    }

    private static void addData(int N) throws IOException {
        st = new StringTokenizer(br.readLine(),&quot;,&quot;);
        for (int i=0; i&amp;lt;N; i++) li.add(Integer.parseInt(st.nextToken()));
    }

    private static void findResult(int N, int M) {
        int cnt = M;
        int ln = N;
        while (cnt&amp;gt;0) {
            List&amp;lt;Integer&amp;gt; n_li = new ArrayList&amp;lt;&amp;gt;();
            for (int j=0; j&amp;lt;ln-1; j++) n_li.add(li.get(j+1)-li.get(j));
            li = new ArrayList&amp;lt;&amp;gt;(n_li);
            cnt--;
            ln--;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <category>1551번</category>
      <category>백준</category>
      <category>수열의 변화</category>
      <category>자바</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/606</guid>
      <comments>https://hminor.tistory.com/606#entry606comment</comments>
      <pubDate>Fri, 13 Dec 2024 22:10:12 +0900</pubDate>
    </item>
    <item>
      <title>[백준, 자바, 6064번] 카잉 달력</title>
      <link>https://hminor.tistory.com/605</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;h2 style=&quot;color: #585f69; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;해당 문제는 처음에 무슨 말인가 하고&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;쭉 보다보니 x,y가 서로 독립적으로 변하는 문제인 것을 확인&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이후 우선 단순히 1씩 증가하고 M과N위를 벗어날 경우&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;나머지를 활용하여 해결하고자 함.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;다만 이렇게 하니 시간 초과가 발생...&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;역시나 정답 비율이 낮은 이유는 있다는 것을 느낌&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그래서 어떻게 해결할 수 있을지 고민하다가&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;뭔가 규칙을 발견하게 됨.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;우선 아래 코드를 보면
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;입력 값이 10 12 3 9의 경우엔&lt;/span&gt; &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;x를 기준으로 y를 변경 후&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;M만큼 계속 y에 더하고 초과 시 나머지로 변경한다면&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;간단히 해결이 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;입력 값이 10 12 7 2의 경우엔&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;출력이 -1로 나오는 것으로 해결 방법에 대해 고민해 본 결과&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;우선 공통적으로 x가 y보다 작은 값이 들어가도록 조건 처리하기&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이후 마찬가지로 10 12 3 9 입력 값처럼 연산을 하지만&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;가장 마지막 줄에 14 20 (2 10) 이후 다시 (2 2) 가 나오는 것을 확인 후&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;y의 값이 계속 반복되는 것을 확인&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그래서 Set을 통해서 y의 값을 추가하며&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;변경된 y의 값이 Set에 존재할 경우 탈출하도록 하여 해결.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이렇게만 하니 또 틀렸다고 나와서&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;입력 값을 아래와 같이 넣어보니&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;1&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;1 1 1 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;원하는 1의 값이 출력이 안되어 조건 처리한 결과&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;아주 힘겹게 퍼센트가 올라가며 해결 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1733830419538&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 10 12 3 9
// 1 1 -&amp;gt; 3 3 -&amp;gt; 13 13 (3 1) -&amp;gt; 13 11 -&amp;gt; (3 11) -&amp;gt; 13 21 (3 9)

// 10 12 7 2
// 12 10 2 7
// 1 1 -&amp;gt; 2 2 [2]-&amp;gt; 14 14 (2 4) [14]-&amp;gt; 14 16 (2 6) [26]-&amp;gt; 14 18 (2 8) 
//	-&amp;gt; 14 20 (2 10) -&amp;gt; 14 22(2 2) -&amp;gt; 14 14 (2 2)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 성공 코드&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

public class _6064 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;
        int T = Integer.parseInt(br.readLine());
        while (T&amp;gt;0) {
            st = new StringTokenizer(br.readLine());
            int M = Integer.parseInt(st.nextToken());
            int N = Integer.parseInt(st.nextToken());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());

            if (x&amp;gt;y) {
                int tmp1 = M;
                int tmp2 = x;
                M = N;
                x = y;
                N = tmp1;
                y = tmp2;
            }

            int result = findKaing(M,N,x,y);
            bw.write(result+&quot;\n&quot;);
            T--;
        }
        bw.flush();
    }

    private static int findKaing(int M, int N, int x, int y) {
        Set&amp;lt;Integer&amp;gt; s_li = new HashSet&amp;lt;&amp;gt;(Arrays.asList(x));
        int cnt = x;
        int now = x;
        boolean state = false;
        if (x!=y) {
            while (true) {
                now=(now+M)%N==0?N:(now+M)%N;
                cnt+=M;
                if (now==y) {
                    state = true;
                    break;
                } else if (s_li.contains(now)) break;
                s_li.add(now);
            }
        } else state = true;
        return state?cnt:-1;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 시간초과 코드&lt;/p&gt;
&lt;pre id=&quot;code_1733830792839&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;
        int T = Integer.parseInt(br.readLine());
        while (T&amp;gt;0) {
            st = new StringTokenizer(br.readLine());
            int M = Integer.parseInt(st.nextToken());
            int N = Integer.parseInt(st.nextToken());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());
            int result = findKaing(M,N,x,y);
            bw.write(result+&quot;\n&quot;);
            T--;
        }
        bw.flush();
    }

    private static int findKaing(int M, int N, int x, int y) {
        int cnt = 1;
        int[] now = {1,1};
        boolean state = x==M&amp;amp;&amp;amp;y==N;
        while (now[0]!=M || now[1]!=N) {
            if (now[0]==x &amp;amp;&amp;amp; now[1]==y) {
                state = true;
                break;
            }
            now[0]=now[0]+1&amp;gt;M?1:now[0]+1;
            now[1]=now[1]+1&amp;gt;N?1:now[1]+1;
            cnt++;
        }
        return state?cnt:-1;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘</category>
      <category>6064번</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자바</category>
      <category>카잉 달력</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/605</guid>
      <comments>https://hminor.tistory.com/605#entry605comment</comments>
      <pubDate>Tue, 10 Dec 2024 20:41:18 +0900</pubDate>
    </item>
    <item>
      <title>[백준, 자바, 5525번] IOIOI</title>
      <link>https://hminor.tistory.com/604</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;challenge&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;h2 style=&quot;color: #585f69; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;해당 문제를 처음 봤을 때는&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;substring으로 특정 문자열을 찾으면 되겠구나 했지만&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이렇게 쉬운데 정답 비율이 낮다는 건, 무슨 의도가 있겠구나 싶었음&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그래도 우선 시도해보고 그에 따라 변화를 주는 것이 좋을 것 같다고 판단하여&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그대로 실행했지만 역시나... 50%까지만 정답&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이후 어떻게 해볼까 고민하다가&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;단순히 I와O의 반복되는 길이를 찾고&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;해당 구간에서 N길이에 따른 문자열의 길이를 카운팅하면 되지 않을까하고&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;알고리즘을 작성한 결과 무난히 통과!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 성공 코드&lt;/p&gt;
&lt;pre id=&quot;code_1733816303992&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int M = Integer.parseInt(br.readLine());
        String s = br.readLine();
        System.out.println(findResult(M,N*2+1,s));
    }
    private static int findResult(int M, int ms_ln, String s) {
        int cnt = 0;
        int ln = 0;
        char[] check = {'I','O'};
        for (int i=0; i&amp;lt;M; i++) {
            if (check[ln%2]==s.charAt(i)) ln++;
            else {
                cnt+=cal(ms_ln, ln);
                ln=check[0]==s.charAt(i)?1:0;
            }
        }
        if (ln!=0) cnt+=cal(ms_ln, ln);
        return cnt;
    }

    private static int cal(int ms_ln, int ln) {
        return ln&amp;gt;=ms_ln?(ln-ms_ln)/2+1:0;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 50% 코드&lt;/p&gt;
&lt;pre id=&quot;code_1733816320197&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int M = Integer.parseInt(br.readLine());
        String s = br.readLine();
        System.out.println(findResult(M,N*2+1,makeString(N),s));
    }
    private static String makeString(int N) {
        StringBuilder sb = new StringBuilder();
        for (int i=0; i&amp;lt;N; i++) sb.append(&quot;IO&quot;);
        sb.append(&quot;I&quot;);
        return sb.toString();
    }

    private static int findResult(int M, int ms_ln, String ms, String s) {
        int cnt = 0;
        for (int i=0; i&amp;lt;=M-ms_ln; i++) {
            if (s.substring(i,i+ms_ln).equals(ms)) cnt++;
        }
        return cnt;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘</category>
      <category>5525번</category>
      <category>IOIOI</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자바</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/604</guid>
      <comments>https://hminor.tistory.com/604#entry604comment</comments>
      <pubDate>Tue, 10 Dec 2024 16:40:09 +0900</pubDate>
    </item>
    <item>
      <title>[백준, 자바, 1389번] 케빈 베이컨의 6단계 법칙</title>
      <link>https://hminor.tistory.com/603</link>
      <description>&lt;figure style=&quot;color: #333333; text-align: left;&quot; contenteditable=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-name=&quot;002&quot; data-emoticon-type=&quot;challenge&quot; data-ke-align=&quot;alignLeft&quot; data-ke-type=&quot;emoticon&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/challenge/large/002.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;h2 style=&quot;color: #585f69; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;해당 문제는 단순히 데이터 추가 후&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;결과를 찾고자는 곳에 가장 마지막 유저를 제외하고&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;BFS로 찾으며, 조건에 따라 mtx에 단계를 변경하는 것으로 해결&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;내가 작성한 풀이에서 아쉬운 점은 예를 들어 N=5의 경우&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;1번은 모든 사람에 대한 조사를 하기에&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;2,3,4,5번의 모든 1번 mtx가 채워져 있기에&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;2번은 2번은 같으니 제외하고&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;3번부터 5번까지만 찾도록 하고 싶은데&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;이를 어떻게 해결할 수 있을지를 고민해도&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;잘 떠오르지 않아 그냥 마지막 사람을 제외한 모든 사람을 BFS로 탐색하는 것으로 해결...&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;
public class _1389 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static int[][] mtx;
    static List&amp;lt;Set&amp;lt;Integer&amp;gt;&amp;gt; relationArr = new ArrayList&amp;lt;&amp;gt;();
    static StringTokenizer st;
    static int[] result;
    public static void main(String[] args) throws IOException {
        st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        mtx = new int[N+1][N+1];
        result = new int[]{-1,-1};
        addData(N,M);
        findResult(N);
        System.out.println(result[0]);
    }

    private static void addData(int N, int M) throws IOException {
        for (int i=0; i&amp;lt;=N; i++) relationArr.add(new HashSet&amp;lt;&amp;gt;());
        for (int i=0; i&amp;lt;M; i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            relationArr.get(a).add(b);
            relationArr.get(b).add(a);
        }
    }

    private static void findResult(int N) {
        for (int i=1; i&amp;lt;=N; i++) {
            if (i!=N) BFS(i,N);
            int hap = 0;
            for (int j=1; j&amp;lt;=N; j++) hap+=mtx[i][j];
            if (result[0]==-1 || result[1]&amp;gt;hap) {
                result[0]=i;
                result[1]=hap;
            }
        }
    }

    private static void BFS(int a, int N) {
        Deque&amp;lt;int[]&amp;gt; dq = new ArrayDeque&amp;lt;&amp;gt;(Arrays.asList(new int[]{a,0}));
        boolean[] visit = new boolean[N+1];
        visit[a]=true;

        while (!dq.isEmpty()) {
            int[] now = dq.pollFirst();
            for (int next: new ArrayList&amp;lt;&amp;gt;(relationArr.get(now[0]))) {
                if (!visit[next]) {
                    dq.add(new int[]{next,now[1]+1});
                    visit[next]=true;
                    if (mtx[a][next]==0) {
                        mtx[a][next]=now[1]+1;
                        mtx[next][a]=now[1]+1;
                    }
                }
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <category>1389번</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자바</category>
      <category>케빈 베이컨의 6단계 법칙</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/603</guid>
      <comments>https://hminor.tistory.com/603#entry603comment</comments>
      <pubDate>Mon, 9 Dec 2024 17:51:02 +0900</pubDate>
    </item>
    <item>
      <title>[백준, 자바, 30804번] 과일 탕후루</title>
      <link>https://hminor.tistory.com/602</link>
      <description>&lt;h2 style=&quot;color: #585f69; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;해당 문제는 뭔가 어려웠다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;우선 처음에는 어떻게 해결할 수 있을지 고민하다가&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;누적합으로 해결 할 수 있지 않을까 했는데&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;생각하다보니 20만 배열의 경우엔 너무 반복이 심할 것 같아서&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;고민을 했지만 우선 진행&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;하지만 역시나 시간초과...&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;그래서 아래에 태그를 확인해보니&amp;nbsp;투 포인터&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;물론 두 개의 인덱스로 어찌어찌 한다는 정도는 알지만&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;어떤 경우에 사용하면 좋은지 이해하고자,&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;우선 개념을 이해하기로 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1733471579914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;주요 개념
	포인터: 배열이나 리스트에서 특정 위치를 가리키는 인덱스입니다.
	두 포인터:
		왼쪽 포인터와 오른쪽 포인터를 초기화하고, 조건에 따라 이동시키면서 필요한 값을 찾습니다.
	시간 복잡도: 보통 **O(N)**으로 동작하며, 완전 탐색(O(N&amp;sup2;))에 비해 효율적입니다.

투 포인터의 활용
	구간 합 문제:
		연속된 부분 구간(subarray)의 합을 빠르게 찾기.
	두 배열의 교집합:
		두 정렬된 배열에서 공통 요소 찾기.
	특정 조건 만족 구간:
		최소 길이의 구간 찾기, 예를 들어 슬라이딩 윈도우와 결합.


장점
	효율적: 시간 복잡도를 줄임.
	메모리 절약: 추가적인 자료 구조 없이 인덱스만으로 해결 가능.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이에 대한 개념과 추가 자료를 참고하여 아래와 같이 해결&lt;/li&gt;
&lt;li&gt;우선 입력 값을 배열에 추가한 뒤&lt;/li&gt;
&lt;li&gt;배열을 순차적으로 돌면서 Map에 해당 인덱스의 값을 key로 두고&amp;nbsp;카운팅&lt;/li&gt;
&lt;li&gt;다만 put을 하며 해당 key의 기존 value를 가져오려고 하다보니&lt;/li&gt;
&lt;li&gt;그냥 get 만 하게 되면 key가 없을 경우 null이기에&lt;/li&gt;
&lt;li&gt;연산을 진행하면 에러처리가 발생&lt;/li&gt;
&lt;li&gt;그래서 getOrDefault 메서드를 활용하여 없을 경우 0으로 초기화하는 작업을 진행&lt;/li&gt;
&lt;li&gt;이후 탐색 구간에 주어진 과일 종류가 3개 이상의 경우엔&lt;/li&gt;
&lt;li&gt;시작 포인트 부터 하나씩 차감 후 종류가 2개가 되도록 만들고&lt;/li&gt;
&lt;li&gt;이후 시작 포인트를 1씩 증가&lt;/li&gt;
&lt;li&gt;마지막으로 while 문 탈출 후&lt;/li&gt;
&lt;li&gt;현재 거리를 계산한 값 중 가장 큰 값을 리턴하여 해결.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 성공 코드(투 포인터)&lt;/p&gt;
&lt;pre id=&quot;code_1733471979076&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

public class _30804 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int[] li;
    public static void main(String[] args) throws IOException {
        int N = Integer.parseInt(br.readLine());
        addFruits(N);
        System.out.println(findManyFruits(N));
    }


    private static void addFruits(int N) throws IOException {
        li = new int[N];
        st = new StringTokenizer(br.readLine());
        for (int i=0; i&amp;lt;N; i++) li[i]=Integer.parseInt(st.nextToken());
    }

    private static int findManyFruits(int N) {
        Map&amp;lt;Integer, Integer&amp;gt; fruits = new HashMap&amp;lt;&amp;gt;();
        int result = 0;
        int s = 0;
        for (int e=0; e&amp;lt;N; e++) {
            fruits.put(li[e],fruits.getOrDefault(li[e],0)+1);
            while (fruits.size()&amp;gt;2) {
                fruits.put(li[s],fruits.get(li[s])-1);
                if (fruits.get(li[s])==0) fruits.remove(li[s]);
                s++;
            }
            if (e-s+1&amp;gt;result) result = e-s+1;
        }
        return result;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 실패 코드(누적합)&lt;/p&gt;
&lt;pre id=&quot;code_1733472011449&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int[][] li;
    public static void main(String[] args) throws IOException {
        int N = Integer.parseInt(br.readLine());
        addFruits(N);
        System.out.println(findManyFruits(N));
    }

    private static void addFruits(int N) throws IOException {
        li = new int[N+1][10];
        st = new StringTokenizer(br.readLine());
        for (int i=1; i&amp;lt;=N; i++) {
            li[i]= Arrays.stream(li[i-1]).toArray();
            li[i][Integer.parseInt(st.nextToken())]++;
        }
    }

    private static int findManyFruits(int N) {
        int result = 0;
        for (int i=1; i&amp;lt;N; i++) { // 기준
            for (int j=i+1; j&amp;lt;=N; j++) { // 이동
                int[] f_cnt = {0,0}; // 과일 종류, 총 개수
                for (int k=0; k&amp;lt;9; k++) {
                    if (li[j][k]-li[i-1][k]!=0) {
                        f_cnt[0]++; // 과일 카운팅
                        f_cnt[1]+=li[j][k]-li[i-1][k]; // 총 개수 카운팅
                        if (f_cnt[0]&amp;gt;2) break;
                    }
                }
                if (!(f_cnt[0]&amp;gt;2)&amp;amp;&amp;amp;f_cnt[1]&amp;gt;result) result=f_cnt[1];
            }
        }
        return result;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘</category>
      <category>30804번</category>
      <category>과일 탕후루</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자바</category>
      <author>hminor</author>
      <guid isPermaLink="true">https://hminor.tistory.com/602</guid>
      <comments>https://hminor.tistory.com/602#entry602comment</comments>
      <pubDate>Fri, 6 Dec 2024 17:01:50 +0900</pubDate>
    </item>
  </channel>
</rss>