<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>juntae_94.log</title>
        <link>https://velog.io/</link>
        <description>🙏</description>
        <lastBuildDate>Sat, 28 Oct 2023 07:58:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>juntae_94.log</title>
            <url>https://velog.velcdn.com/images/juntae_94/profile/abe1100f-655c-469c-af61-78e0ae7a064d/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. juntae_94.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/juntae_94" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[1926 : 그림]]></title>
            <link>https://velog.io/@juntae_94/1926-%EA%B7%B8%EB%A6%BC</link>
            <guid>https://velog.io/@juntae_94/1926-%EA%B7%B8%EB%A6%BC</guid>
            <pubDate>Sat, 28 Oct 2023 07:58:37 GMT</pubDate>
            <description><![CDATA[<h2 id="☀️-문제-링크">☀️ 문제 링크</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/1926">https://www.acmicpc.net/problem/1926</a></li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/b66a0c79-ab94-414a-9798-7c0288e0404a/image.png" alt=""></p>
<h2 id="🌻-문제-간단한-설명">🌻 문제 간단한 설명</h2>
<blockquote>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/921e5a60-6306-4a9b-8536-7fca9ec8419d/image.png" alt=""></p>
</blockquote>
<ul>
<li><code>DFS, BFS</code> 를 통해서 그림의 개수를 구하고, 그림의 최댓값을 찾는 문제다.</li>
</ul>
<h2 id="⚡️-풀이">⚡️ 풀이</h2>
<h3 id="🌝-전체-코드">🌝 전체 코드</h3>
<h4 id="dfs">DFS</h4>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
    static int Y;
    static int X;
    static int count;
    static int[] dy = {1, 0, -1, 0};
    static int[] dx = {0, 1, 0, -1};
    static String[][] map;
    static boolean[][] isVisited;

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

        Y = Integer.parseInt(st.nextToken());
        X = Integer.parseInt(st.nextToken());

        map = new String[Y][X];
        isVisited = new boolean[Y][X];

        for (int i = 0; i &lt; Y; i++) {
            map[i] = br.readLine().split(&quot; &quot;);
        }

        List&lt;Integer&gt; answer = new ArrayList&lt;&gt;();
        for (int i = 0; i &lt; Y; i++) {
            for (int j = 0; j &lt; X; j++) {
                count = 0;
                if (!isVisited[i][j] &amp;&amp; map[i][j].equals(&quot;1&quot;)) {
                    dfs(i, j);
                    answer.add(count);
                }
            }
        }

        Collections.sort(answer);
        System.out.println(answer.size());
        System.out.println(answer.size() == 0 ? 0 : answer.get(answer.size() - 1));
    }

    private static void dfs(int y, int x) {
        isVisited[y][x] = true;
        count++;
        for (int i = 0; i &lt; 4; i++) {
            int ny = y + dy[i];
            int nx = x + dx[i];
            if (ny &lt; 0 || nx &lt; 0 || ny &gt;= Y || nx &gt;= X) {
                continue;
            }
            if (!isVisited[ny][nx] &amp;&amp; map[ny][nx].equals(&quot;1&quot;)) {
                dfs(ny, nx);
            }
        }
    }
}</code></pre>
<h4 id="bfs">BFS</h4>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static int Y;
    static int X;
    static int count;
    static int[] dy = {1, 0, -1, 0};
    static int[] dx = {0, 1, 0, -1};
    static String[][] map;
    static boolean[][] isVisited;

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

        Y = Integer.parseInt(st.nextToken());
        X = Integer.parseInt(st.nextToken());

        map = new String[Y][X];
        isVisited = new boolean[Y][X];

        for (int i = 0; i &lt; Y; i++) {
            map[i] = br.readLine().split(&quot; &quot;);
        }

        List&lt;Integer&gt; answer = new ArrayList&lt;&gt;();
        for (int i = 0; i &lt; Y; i++) {
            for (int j = 0; j &lt; X; j++) {
                count = 0;
                if (!isVisited[i][j] &amp;&amp; map[i][j].equals(&quot;1&quot;)) {
                    bfs(i, j);
                    answer.add(count);
                }
            }
        }

        Collections.sort(answer);
        System.out.println(answer.size());
        System.out.println(answer.size() == 0 ? 0 : answer.get(answer.size() - 1));
    }

    private static void bfs(int y, int x) {
        Queue&lt;Point&gt; queue = new LinkedList&lt;&gt;();
        queue.add(new Point(y, x));
        isVisited[y][x] = true;
        while (!queue.isEmpty()) {
            Point point = queue.poll();
            count++;
            for (int i = 0; i &lt; 4; i++) {
                int ny = point.y + dy[i];
                int nx = point.x + dx[i];
                if (ny &lt; 0 || nx &lt; 0 || ny &gt;= Y || nx &gt;= X) {
                    continue;
                }
                if (!isVisited[ny][nx] &amp;&amp; map[ny][nx].equals(&quot;1&quot;)) {
                    queue.add(new Point(ny, nx));
                    isVisited[ny][nx] = true;
                }
            }
        }
    }

    static class Point {
        int y;
        int x;

        public Point(int y, int x) {
            this.y = y;
            this.x = x;
        }
    }
}</code></pre>
<h3 id="🌛-코드별-설명">🌛 코드별 설명</h3>
<ul>
<li>값 입력받기, 배열 생성 부분은 생략</li>
</ul>
<h4 id="탐색시작">탐색시작</h4>
<pre><code class="language-java">// 그림의 갯수를 넣을 리스트 생성
List&lt;Integer&gt; answer = new ArrayList&lt;&gt;();
for (int i = 0; i &lt; Y; i++) {
    for (int j = 0; j &lt; X; j++) {
        // 그림의 넓이를 초기화 작업
        count = 0;
        if (!isVisited[i][j] &amp;&amp; map[i][j].equals(&quot;1&quot;)) {
            bfs(i, j);
            // 탐색이 끝나면 count = 연결된 그림의 넓이이므로 답에 추가
            answer.add(count);
        }
    }
}</code></pre>
<pre><code class="language-java">// BFS
private static void bfs(int y, int x) {
    Queue&lt;Point&gt; queue = new LinkedList&lt;&gt;();
    // 시작 지점 삽입
    queue.add(new Point(y, x));
    // 방문 체크
    isVisited[y][x] = true;
    while (!queue.isEmpty()) {
        Point point = queue.poll();
        // 그림의 넓이++;
        count++;
        for (int i = 0; i &lt; 4; i++) {
            // 현위치에서 상하좌우 좌표
            int ny = point.y + dy[i];
            int nx = point.x + dx[i];
            // map, isVisited의 값을 넘지않는지 체크
            if (ny &lt; 0 || nx &lt; 0 || ny &gt;= Y || nx &gt;= X) {
                continue;
            }
            // 방문하지 않았고, 그림이 연결되어있으면 탐색영역 추가
            if (!isVisited[ny][nx] &amp;&amp; map[ny][nx].equals(&quot;1&quot;)) {
                // 이동가능하면 탐색영역 추가
                queue.add(new Point(ny, nx));
                // BFS는 while문에서 돌기때문에 따로 방문체크
                // 반면 DFS는 초기에 한번만 방문체크 하면됨(재귀)
                isVisited[ny][nx] = true;
            }
        }
    }
}

static class Point {
    int y;
    int x;

    public Point(int y, int x) {
        this.y = y;
        this.x = x;
    }
}</code></pre>
<pre><code class="language-java">// DFS 위 BFS에 설명했으므로 생략
private static void dfs(int y, int x) {
    isVisited[y][x] = true;
    count++;
    for (int i = 0; i &lt; 4; i++) {
        int ny = y + dy[i];
        int nx = x + dx[i];
        if (ny &lt; 0 || nx &lt; 0 || ny &gt;= Y || nx &gt;= X) {
            continue;
        }
        if (!isVisited[ny][nx] &amp;&amp; map[ny][nx].equals(&quot;1&quot;)) {
            dfs(ny, nx);
        }
    }
}</code></pre>
<h4 id="정답-출력">정답 출력</h4>
<pre><code class="language-java">// 오름차순 정렬 정답 도출
Collections.sort(answer);
System.out.println(answer.size());
System.out.println(answer.size() == 0 ? 0 : answer.get(answer.size() - 1));

// 내림차순 정렬 정답 도출
// answer.sort(Collections.reverseOrder()); 도 가능
Collections.sort(answer, Collections.reverseOrder());
System.out.println(answer.size());
System.out.println(answer.size() == 0 ? 0 : answer.get(0));</code></pre>
<h2 id="🌞-끝으로">🌞 끝으로</h2>
<blockquote>
<p>DFS, BFS는 정해진 틀이 있으므로 그것을 잘 활용하는게 중요한것 같다. 대부분 저 틀을 활용해서 문제를 풀어왔지만, 조금더 어려운 문제는 3차원 배열을 활용하거나 정답을 다른방식으로 도출하는게 문제일것이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[17615 : 볼 모으기]]></title>
            <link>https://velog.io/@juntae_94/17615-%EB%B3%BC-%EB%AA%A8%EC%9C%BC%EA%B8%B0</link>
            <guid>https://velog.io/@juntae_94/17615-%EB%B3%BC-%EB%AA%A8%EC%9C%BC%EA%B8%B0</guid>
            <pubDate>Fri, 27 Oct 2023 14:08:37 GMT</pubDate>
            <description><![CDATA[<h2 id="☀️-문제-링크">☀️ 문제 링크</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/17615">https://www.acmicpc.net/problem/17615</a></li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/e4f5e6b3-2948-4ddb-97c9-0d8aa44db1e6/image.png" alt=""><img src="https://velog.velcdn.com/images/juntae_94/post/91d9d29c-a257-4e98-9829-8062541a1286/image.png" alt=""></p>
<h2 id="🌻-문제-간단한-설명">🌻 문제 간단한 설명</h2>
<blockquote>
<ul>
<li>그리디 알고리즘을 통해 해결할 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>색깔별로 양쪽으로 나눌경우 이동거리의 최소값을 구하는 문제이다.
<img src="https://velog.velcdn.com/images/juntae_94/post/9d74ebbe-1e58-4596-8e9b-4fcb0ec200c4/image.png" alt=""><ul>
<li>RBBB<code>R</code>BRRR : 저걸 오른쪽으로 옮긴다.</li>
<li><code>R</code>BBBBRRRR(이동횟수 1) : 저걸 오른쪽으로 옮긴다.</li>
<li>BBBBRRRRR(이동횟수 2) 끝<ul>
<li>다른방법도있음</li>
</ul>
</li>
<li><code>R</code>BBBRBRRRR(이동횟수 1) : 4번자리로 이동</li>
<li>BBBRR<code>B</code>RRRR(이동횟수 2) : 3번자리로 이동 끝</li>
</ul>
</li>
</ul>
<h2 id="⚡️-풀이">⚡️ 풀이</h2>
<h3 id="🌝-전체-코드">🌝 전체 코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());
        char[] balls = br.readLine().toCharArray();

        int redBall = 0;
        int blueBall = 0;

        for (char ball : balls) {
            if (ball == &#39;R&#39;) {
                redBall++;
            } else {
                blueBall++;
            }
        }

        int searchFrontRed = redBall - searchFront(balls, &#39;R&#39;);
        int searchFrontBlue = blueBall - searchFront(balls, &#39;B&#39;);
        int searchBackRed = redBall - searchBack(balls, &#39;R&#39;);
        int searchBackBlue = blueBall - searchBack(balls, &#39;B&#39;);

        System.out.println(Math.min(searchFrontRed, Math.min(searchFrontBlue, Math.min(searchBackRed, searchBackBlue))));
    }

    private static int searchFront(char[] balls, char color) {
        int count = 0;
        for (char ball : balls) {
            if (ball == color) {
                count++;
            } else {
                break;
            }
        }

        return count;
    }

    private static int searchBack(char[] balls, char color) {
        int count = 0;
        for (int i = balls.length - 1; i &gt;= 0; i--) {
            if (balls[i] == color) {
                count++;
            } else {
                break;
            }
        }

        return count;
    }
}</code></pre>
<h3 id="🌛-코드별-설명">🌛 코드별 설명</h3>
<h4 id="앞에서-부터-탐색">앞에서 부터 탐색</h4>
<blockquote>
<ul>
<li>만약 왼쪽으로 <code>R</code>을 몰아버릴 경우 (RBBBRBRRR -&gt; RRRRRBBBB)<ul>
<li>전체 <code>R</code>볼의 개수<code>(5)</code> - 왼쪽에서 연속된 <code>R</code>볼의 갯수<code>(1)</code>이다.</li>
<li>RBBB<code>R</code>BRRR -&gt; RRBBBBRRR (Count 1)</li>
<li>RRBBBB<code>R</code>RR -&gt; RRRBBBBRR (Count 2)</li>
<li>RRRBBBB<code>R</code>R -&gt; RRRRBBBBR (Count 3)</li>
<li>RRRRBBBB<code>R</code> -&gt; RRRRRBBBB (Count 4)</li>
</ul>
</li>
</ul>
</blockquote>
<pre><code class="language-java">int searchFrontRed = redBall - searchFront(balls, &#39;R&#39;);

private static int searchFront(char[] balls, char color) {
    int count = 0;
    for (char ball : balls) {
        if (ball == color) {
            count++;
        } else {
            break;
        }
    }

    return count;
}</code></pre>
<h4 id="뒤에서-부터-탐색">뒤에서 부터 탐색</h4>
<blockquote>
<ul>
<li>만약 오른쪽으로 <code>R</code>을 몰아버릴 경우(RBBBRBRRR -&gt; BBBBRRRRR)<ul>
<li>전체 <code>R</code>볼의 개수<code>(5)</code> - 오른쪽에서 연속된 <code>R</code>볼의 갯수<code>(3)</code>이다.</li>
<li>RBBB<code>R</code>BRRR -&gt; RBBBBRRRR (Count 1)</li>
<li><code>R</code>BBBBRRRR -&gt; BBBBRRRRR (Count 2)</li>
</ul>
</li>
</ul>
</blockquote>
<pre><code class="language-java">int searchBackRed = redBall - searchBack(balls, &#39;R&#39;);

private static int searchBack(char[] balls, char color) {
    int count = 0;
    for (int i = balls.length - 1; i &gt;= 0; i--) {
        if (balls[i] == color) {
            count++;
        } else {
            break;
        }
    }

    return count;
}</code></pre>
<h2 id="🌞-끝으로">🌞 끝으로</h2>
<blockquote>
<p>그리디 알고리즘 문제를 풀어봤다.
그리디 알고리즘은 주어진 상황에서 최적해를 구하는 알고리즘이지 전체적으로 봤을때 최적해를 보장하지 않는 알고리즘이다.
그래서 <code>앞에 R, 앞에 B, 뒤에 R, 뒤에 B</code> 이렇게 주어진 조건에 한에서 최적해를 구하고 그 중에서 Math.min을 통해서 최적해를 찾았다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[1446 : 지름길]]></title>
            <link>https://velog.io/@juntae_94/1446-%EC%A7%80%EB%A6%84%EA%B8%B8</link>
            <guid>https://velog.io/@juntae_94/1446-%EC%A7%80%EB%A6%84%EA%B8%B8</guid>
            <pubDate>Thu, 26 Oct 2023 12:53:19 GMT</pubDate>
            <description><![CDATA[<h2 id="☀️-문제-링크">☀️ 문제 링크</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/1446">https://www.acmicpc.net/problem/1446</a></li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/f5abe111-4a73-4ce2-b907-20bc2a4a5cfa/image.png" alt=""></p>
<h2 id="🌻-문제-간단한-설명">🌻 문제 간단한 설명</h2>
<blockquote>
<ul>
<li>DP를 활용해서 최소 이동거리를 구하는 문제이다.
<img src="https://velog.velcdn.com/images/juntae_94/post/0852768d-fb70-46f2-8b0c-0746e06c9b5e/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>if(지름길이 있고 &amp;&amp; 그냥 이동하는 거리 &lt; 지름길을 이용하는 거리) 일경우 지름길을 선택한다.<ul>
<li>예) 0 -&gt; 50 (그냥 이동거리 <code>50</code>)</li>
<li>지름길 <code>(0 50 10)</code> 이용시 이동거리 <code>10</code></li>
<li>50 &lt; 10 이므로 <code>dp[50]</code> 의 값은 10 이다.</li>
</ul>
</li>
</ul>
<h2 id="⚡️-풀이">⚡️ 풀이</h2>
<h3 id="🌝-전체-코드">🌝 전체 코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

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

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

        int[] dp = new int[M + 1];
        int[][] shortcuts = new int[N][3];

        for (int i = 0; i &lt; N; i++) {
            shortcuts[i] = Arrays.stream(br.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        }

        Arrays.sort(shortcuts, (o1, o2) -&gt; o1[0] - o2[0]);

        for (int i = 1; i &lt;= M; i++) {
            dp[i] = dp[i - 1] + 1;
            for (int[] shortcut : shortcuts) {
                if (i == shortcut[1]) {
                    dp[i] = Math.min(dp[i], dp[shortcut[0]] + shortcut[2]);
                }
            }
        }

        System.out.println(dp[M]);
    }
}</code></pre>
<h3 id="🌛-코드별-설명">🌛 코드별 설명</h3>
<ul>
<li>입력받고 배열 생성하는 부분은 생략한다.</li>
</ul>
<h4 id="정렬">정렬</h4>
<blockquote>
<ul>
<li>지름길의 시작지점을 기준으로 정렬해준다.</li>
</ul>
</blockquote>
<ul>
<li>정렬에는 다양한 방법이 있다.</li>
</ul>
<pre><code class="language-java">// 참고로 이건 오름차순
Arrays.sort(shortcuts, (o1, o2) -&gt; o1[0] - o2[0]);

or

Arrays.sort(shortcuts, Comparator.comparingInt(o -&gt; o[0]));

// 이건 내림차순
Arrays.sort(shortcuts, (o1, o2) -&gt; o2[0] - o1[0]);</code></pre>
<h4 id="dp-값-입력--정답-출력">DP 값 입력 &amp; 정답 출력</h4>
<pre><code class="language-java">for (int i = 1; i &lt;= M; i++) {
    // dp[1] = 1 거리 기본값 저장
    dp[i] = dp[i - 1] + 1;
    // 지름길 하나씩 순회하면서 탐색 (최대길이 12)
    for (int[] shortcut : shortcuts) {
        // i = 현재거리 / shortcut[1] = 지름길 도착위치
        if (i == shortcut[1]) {
            // Math.min의 비교값 설명
            // dp[i] -&gt; 지름길을 타지 않았을 경우의 거리
            // dp[shortcut[0](지름길 시작지점)] -&gt; 지름길 시작지점의 최소이동거리
            // shrtcut[2] -&gt; 지름길을 이동했을 경우 소요 이동거리
            dp[i] = Math.min(dp[i], dp[shortcut[0]] + shortcut[2]);
        }
    }
}

System.out.println(dp[M]);</code></pre>
<h2 id="🌞-끝으로">🌞 끝으로</h2>
<blockquote>
<p>DP의 문제의 핵심은 점화식을 찾는것이다.
어떻게  문제의 규칙성을 파악하고 어떻게 문제를 해결해야할지 생각할 시간이 많이 필요한 문제이다. 화이팅</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[14940 : 쉬운 최단거리]]></title>
            <link>https://velog.io/@juntae_94/14940-%EC%89%AC%EC%9A%B4-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC</link>
            <guid>https://velog.io/@juntae_94/14940-%EC%89%AC%EC%9A%B4-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC</guid>
            <pubDate>Wed, 25 Oct 2023 13:39:17 GMT</pubDate>
            <description><![CDATA[<h2 id="☀️-문제-링크">☀️ 문제 링크</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/14940">https://www.acmicpc.net/problem/14940</a></li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/2fc14a5b-9317-40da-b32d-cbfc49711291/image.png" alt=""></p>
<h2 id="🌻-문제-간단한-설명">🌻 문제 간단한 설명</h2>
<blockquote>
<ul>
<li>BFS 알고리즘을 사용하는 문제이다.</li>
</ul>
</blockquote>
<ul>
<li>메모리 제한이 있기 때문에 무턱대고 <code>System.out.println</code>을 사용해선 안된다. </li>
<li>DFS, BFS는 거의 틀이 잡혀있기 때문에 문제를 많이 풀면 이해하기 쉬울 것이다.</li>
</ul>
<h2 id="⚡️-풀이">⚡️ 풀이</h2>
<h3 id="🌝-전체-코드">🌝 전체 코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    static int Y;
    static int X;
    static int[] dy = {1, 0, -1, 0};
    static int[] dx = {0, 1, 0, -1};
    static int[][] map;
    static boolean[][] isVisited;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        Y = Integer.parseInt(st.nextToken());
        X = Integer.parseInt(st.nextToken());

        map = new int[Y][X];
        isVisited = new boolean[Y][X];
        for (int i = 0; i &lt; Y; i++) {
            map[i] = Arrays.stream(br.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        }

        boolean flag = false;
        int startY = 0, startX = 0;
        for (int i = 0; i &lt; Y; i++) {
            if (!flag) {
                for (int j = 0; j &lt; X; j++) {
                    if (map[i][j] == 2) {
                        map[i][j] = 0;
                        flag = true;
                        startY = i;
                        startX = j;
                        break;
                    }
                }
            }
        }

        bfs(startY, startX);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i &lt; Y; i++) {
            for (int j = 0; j &lt; X; j++) {
                if (!isVisited[i][j] &amp;&amp; map[i][j] == 1) {
                    sb.append(-1).append(&quot; &quot;);
                } else {
                    sb.append(map[i][j]).append(&quot; &quot;);
                }
            }
            sb.append(&quot;\n&quot;);
        }

        System.out.println(sb);
    }

    private static void bfs(int startY, int startX) {
        Queue&lt;Point&gt; queue = new LinkedList&lt;&gt;();
        queue.add(new Point(startY, startX));
        isVisited[startY][startX] = true;
        while (!queue.isEmpty()) {
            Point point = queue.poll();
            int y = point.y;
            int x = point.x;
            for (int i = 0; i &lt; 4; i++) {
                int ny = y + dy[i];
                int nx = x + dx[i];
                if (ny &lt; 0 || nx &lt; 0 || ny &gt;= Y || nx &gt;= X) {
                    continue;
                }
                if (!isVisited[ny][nx] &amp;&amp; map[ny][nx] == 1) {
                    queue.add(new Point(ny, nx));
                    isVisited[ny][nx] = true;
                    map[ny][nx] = map[y][x] + 1;
                }
            }
        }
    }

    static class Point {
        int y;
        int x;

        public Point(int y, int x) {
            this.y = y;
            this.x = x;
        }
    }
}</code></pre>
<h3 id="🌛-코드별-설명">🌛 코드별 설명</h3>
<h4 id="시작-지점-설정--값-초기화">시작 지점 설정 &amp; 값 초기화</h4>
<blockquote>
<ul>
<li>시작지점이 따로 정해져있지 않고 숫자 2가 있는곳에서 출발 한다.</li>
</ul>
</blockquote>
<ul>
<li>또한 새로운 <code>int[][]</code>을 만들지 않고 덮어씌울 예정이라 값을 <code>0</code>으로 초기화 했다.</li>
<li>물론 새로운 <code>answer[][]</code>을 만들어서 해도된다.(해보니 통과함)<ul>
<li><del>난 이게 편한듯</del></li>
</ul>
</li>
</ul>
<pre><code class="language-java">boolean flag = false;
int startY = 0, startX = 0;
for (int i = 0; i &lt; Y; i++) {
        if (!flag) {
            for (int j = 0; j &lt; X; j++) {
                if (map[i][j] == 2) {
                    map[i][j] = 0;
                    flag = true;
                    startY = i;
                    startX = j;
                    break;
                }
            }
      }
}

bfs(startY, startX);</code></pre>
<h4 id="정답-출력">정답 출력</h4>
<blockquote>
<ul>
<li>여기서 메모리 초과를 해서 시간이 오래 걸렸다.</li>
</ul>
</blockquote>
<ul>
<li><code>원래 갈 수 있는 땅인 부분 중에서 도달할 수 없는 위치는 -1을 출력한다.</code></li>
<li>그래서 두 코드의 메모리의 차이를 알고 싶어서 찾아봤는데 <code>메모리 차이가 거의 없다고 한다.</code> 하지만 실제 문제를 의도하고 출제를 하였다면 문제는 틀렸다. 최대한 메모리를 적게 사용하는 방법을 택해야겠다.
<img src="https://velog.velcdn.com/images/juntae_94/post/c74c0e48-ef10-42ee-b6f2-34ac29841b93/image.png" alt=""></li>
</ul>
<hr>
<p>Before (메모리  초과)</p>
<pre><code class="language-java">for (int i = 0; i &lt; Y; i++) {
    for (int j = 0; j &lt; X; j++) {
        if (!isVisited[i][j] &amp;&amp; map[i][j] == 1) {
            map[i][j] = -1;
        }
    }
}

StringBuilder sb = new StringBuilder();
for (int i = 0; i &lt; Y; i++) {
    sb.append(Arrays.stream(map[i])
                    .mapToObj(String::valueOf)
                    .reduce((x, y) -&gt; x + &quot; &quot; + y)
                    .orElse(&quot;&quot;))
                    .append(&quot;\n&quot;);
}

System.out.println(sb);</code></pre>
<hr>
<p>After (성공)</p>
<pre><code class="language-java">StringBuilder sb = new StringBuilder();
for (int i = 0; i &lt; Y; i++) {
    for (int j = 0; j &lt; X; j++) {
        if (!isVisited[i][j] &amp;&amp; map[i][j] == 1) {
            sb.append(-1).append(&quot; &quot;);
        } else {
            sb.append(map[i][j]).append(&quot; &quot;);
        }
    }
    sb.append(&quot;\n&quot;);
}

System.out.println(sb);</code></pre>
<h4 id="bfs">BFS</h4>
<blockquote>
<ul>
<li>전형적인 BFS 코드이다.</li>
</ul>
</blockquote>
<ul>
<li><code>2(시작지점)</code> 지점을 <code>0</code>으로 초기화를 해줬기 때문에 마지막에 이전의 칸의 값을 <code>+ 1</code> 해줬다.</li>
</ul>
<pre><code class="language-java">private static void bfs(int startY, int startX) {
    Queue&lt;Point&gt; queue = new LinkedList&lt;&gt;();
    queue.add(new Point(startY, startX));
    isVisited[startY][startX] = true;
    while (!queue.isEmpty()) {
        Point point = queue.poll();
        int y = point.y;
        int x = point.x;
        for (int i = 0; i &lt; 4; i++) {
            int ny = y + dy[i];
            int nx = x + dx[i];
            if (ny &lt; 0 || nx &lt; 0 || ny &gt;= Y || nx &gt;= X) {
                continue;
            }
            if (!isVisited[ny][nx] &amp;&amp; map[ny][nx] == 1) {
                queue.add(new Point(ny, nx));
                isVisited[ny][nx] = true;
                map[ny][nx] = map[y][x] + 1;
            }
        }
    }
}</code></pre>
<h2 id="🌞-끝으로">🌞 끝으로</h2>
<blockquote>
<p>시간복잡도, 공간복잡도, 메모리를 계산하면서 풀려고 해야겠다. 아직까지 그 부분이 조금 부족한듯하다. (솔직히 잘 모름) 
만약 구글링이 안 됐으면 거의 하루종일 못 풀었을 듯하다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로세스? 스레드?]]></title>
            <link>https://velog.io/@juntae_94/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8A%A4%EB%A0%88%EB%93%9C</link>
            <guid>https://velog.io/@juntae_94/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8A%A4%EB%A0%88%EB%93%9C</guid>
            <pubDate>Sat, 05 Aug 2023 14:30:32 GMT</pubDate>
            <description><![CDATA[<p><img src="https://1.bp.blogspot.com/-9R5Jw0K3Ka0/YO7BbvOj0uI/AAAAAAAAouE/z8AM-YcqbVIjvckLNSVCvCpAKhnNVFy0ACLcBGAsYHQ/w539-h330/Process%2Band%2Bthreads.png" alt=""></p>
<h1 id="프로세스process">프로세스(process)</h1>
<blockquote>
<ul>
<li><code>프로그램</code>이 메모리에 올라가 <code>인스턴스화</code> 된것 (<code>독립적</code>으로 실행되는 개체)</li>
</ul>
</blockquote>
<ul>
<li>프로세스 간의 자원 공유는 좀 더 복잡한 절차를 거쳐 이루어짐</li>
<li>프로세스는 최소 1개의 <code>스레드(thread)</code>를 존재</li>
</ul>
<h2 id="프로세스의-메모리-구조">프로세스의 메모리 구조</h2>
<p><img src="https://gabrieletolomei.files.wordpress.com/2013/10/program_in_memory2.png" alt=""></p>
<h3 id="스택">스택</h3>
<ul>
<li>프로세스의 <code>실행 시</code> <code>함수 호출</code>과 <code>지역 변수</code>를 저장하고 관리하는 메모리 영역</li>
<li>메모리가 늘거나 줄어들수 있음<h3 id="힙">힙</h3>
</li>
<li>프로그램 <code>실행 중</code> <code>동적 할당</code>을 위해 사용되는 메모리 영역<h3 id="데이터-영역">데이터 영역</h3>
</li>
<li>프로세스의 <code>전역 변수</code>와 <code>정적 변수</code>를 저장하는 공간<h3 id="코드-영역">코드 영역</h3>
</li>
<li>프로그램의 코드</li>
</ul>
<h2 id="pcb">PCB</h2>
<p><img src="https://prepinsta.com/wp-content/uploads/2023/01/Process-Control-block-in-os.webp" alt=""></p>
<blockquote>
<ul>
<li>운영체제에서 프로세스에 대한 메타데이터를 저장한 데이터</li>
</ul>
</blockquote>
<ul>
<li><p>일반 사용자가 접근하지 못하도록 <code>커널 스택</code>의 가장 앞부분에서 관리</p>
</li>
<li><p>프로세스 관리와 스케줄링을 용이하게 하고, 프로세스 간 전환(context switch)을 원활하게 수행</p>
</li>
<li><p><strong>프로세스 식별자(Process ID)</strong> : 프로세스를 고유하게 식별하는 번호</p>
</li>
<li><p><strong>프로세스 상태(Process State)</strong> : 프로세스의 현재 상태를 나타내는 정보</p>
</li>
<li><p><strong>프로그램 카운터(Program Counter, PC)</strong> : 프로세스에서 실행해야 할 다음 명령어의 주소에 대한 포인터</p>
</li>
<li><p><strong>레지스터 상태(Register State)</strong> : 프로세스가 실행되는 동안 사용되는 레지스터들의 상태를 저장(이 정보는 <code>프로세스 간 전환</code> 시 필요)</p>
</li>
<li><p><strong>메모리 관리 정보(Memory Management)</strong> : 프로세스의 메모리 할당을 관리하기 위한 정보</p>
</li>
<li><p><strong>프로세스 우선순위(Process Priority)</strong> : 프로세스 대기열에서 스케줄링 알고리즘에 따라 실행 순서를 정하기 위해 사용되는 <code>우선순위 값</code></p>
</li>
<li><p><strong>입출력 상태 및 정보(Input/Output Status, Information)</strong>: 프로세스에 할당된 I/O 디바이스 목록</p>
</li>
<li><p><strong>계정 정보(Accounting Information)</strong> : 프로세스 실행에 사용된 CPU사용량, 실행한 유저의 정보</p>
</li>
</ul>
<h3 id="컨텍스트-스위칭context-switching">컨텍스트 스위칭(context switching)</h3>
<blockquote>
<ul>
<li>운영 체제에서 실행 중인 프로세스(혹은 스레드)를 중단하고 다른 프로세스(혹은 스레드)로 전환하는 과정</li>
</ul>
</blockquote>
<ul>
<li>여러 프로세스들이 동시에 실행되는 것처럼 느껴지게 하며, 프로세서의 사용을 효율적으로 관리(아주 빠른 속도로 실행)</li>
</ul>
<p><img src="https://afteracademy.com/images/what-is-context-switching-in-operating-system-context-switching-flow.png" alt=""></p>
<blockquote>
<h4 id="실행-순서">실행 순서</h4>
</blockquote>
<ol>
<li>현재 실행 중인 프로세스(<code>Process P1</code>)의 상태를 <code>PCB</code>에 저장</li>
<li>다음 실행할 프로세스(<code>Process P2</code>)를 결정</li>
<li>프로세스의(<code>Process P2</code>) <code>PCB</code>에서 프로세서 상태와 관련된 정보를 가져와 프로세서에 로드</li>
</ol>
<h1 id="스레드thread">스레드(thread)</h1>
<blockquote>
<ul>
<li>프로세스 내에서 <code>독립적</code>으로 실행되는 작업의 흐름</li>
</ul>
</blockquote>
<ul>
<li>프로세스 내의 코드와 자원을 <code>공유</code>(스레드 간에 데이터 공유와 통신이 상대적으로 간단)</li>
<li>자신만의 <code>스택 공간</code>을 가지며, 프로세스의 다른 스레드와 <code>힙 공간, 전역 변수, 프로세스 코드 등을 공유</code></li>
<li>CPU에서 실행되는 단위(unit of execution)</li>
</ul>
<h1 id="멀티스레딩--멀티프로세싱">멀티스레딩 &amp; 멀티프로세싱</h1>
<p><img src="https://miro.medium.com/v2/resize:fit:763/1*QiaqQ0HLT4Iy0N608A5mVA.png" alt=""></p>
<h2 id="멀티스레딩">멀티스레딩</h2>
<blockquote>
<ul>
<li>프로세스 내 작업을 여러 개의 스레드, 멀티스레드로 처리하는 기법</li>
</ul>
</blockquote>
<ul>
<li>스레드끼리 메모리, 파일, 그리고 네트워크 리소스와 같은 프로세스 내부의 코드와 데이터를 공유</li>
<li>한 스레드가 중단 되어도 다른 스레드는 실행 상태일 수 있기 때문에 중단되지 않는 빠른 처리 가능(<code>동시성</code>)</li>
<li>한 스레드에 문제가 생기면 다른 스레드에 영향을 끼쳐 프로세스에 영향을 줄수도 있음</li>
</ul>
<p><img src="https://www.baeldung.com/wp-content/uploads/sites/4/2020/07/multithreading.png" alt=""></p>
<h2 id="멀티프로세싱">멀티프로세싱</h2>
<blockquote>
<ul>
<li>여러 개의 프로세서(CPU)가 동시에 작업을 수행하는 컴퓨팅 방식</li>
</ul>
</blockquote>
<ul>
<li>여러 프로세스들 또는 스레드들을 <code>병렬</code>로 처리(프로세스 중 문제가 발생되더라도 다른프로세스를 이용 -&gt; 신뢰성 높음)</li>
</ul>
<p><img src="https://techdifferences.com/wp-content/uploads/2016/09/Symmetric-Multiprocessing-Vs-Asymmetric-Multiprocessing.jpg" alt=""></p>
<h3 id="대칭-다중처리smp-symmetric-multiprocessing">대칭 다중처리(SMP, Symmetric multiprocessing)</h3>
<blockquote>
<ul>
<li>두 개 이상의 프로세서가 메모리와 기타 시스템 리소스를 공유하는 방식</li>
</ul>
</blockquote>
<ul>
<li>모든 CPU가 <code>동등한 상태</code>로 동작하며, 운영 체제에서 각 프로세서에 작업을 <code>균등</code>하게 분산하는 스케줄링 방식</li>
<li>부하 <code>분산을 효과적</code>으로 수행(한 프로세서가 필요할 때 다른 프로세서의 작업을 쉽게 전달가능)</li>
</ul>
<h3 id="비대칭-다중처리asmp-asymmetric-multiprocessing">비대칭 다중처리(ASMP, Asymmetric multiprocessing)</h3>
<blockquote>
<ul>
<li>각 프로세서가 전용 역할을 수행하고 특정 작업이나 리소스에 대한 권한이 할당된 구조</li>
</ul>
</blockquote>
<ul>
<li>특정 프로세서가 시스템 관리 업무(Master)를 전담하고, 나머지 프로세서들이 사용자 작업(Slave)을 전담</li>
<li>특정 프로세서가 오버헤드를 처리하므로, 다른 프로세서들이 더 효과적으로 동작</li>
</ul>
<h2 id="📎-참고자료">📎 참고자료</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=QmtYKZC0lMU&amp;ab_channel=%EC%89%AC%EC%9A%B4%EC%BD%94%EB%93%9C">프로세스, 스레드, 멀티태스킹, 멀티스레딩, 멀티프로세싱, 멀티프로그래밍, 이 모든 것을 한 방에 깔끔하게 설명합니다!! 콘텐츠 퀄리티 만족하실 겁니다!
</a></li>
<li><a href="https://www.youtube.com/watch?v=sJAcnXquSd4&amp;ab_channel=%ED%81%B0%EB%8F%8C%EC%9D%98%ED%84%B0%EC%A0%84">[CS전공지식면접] 프로세스와 스레드의 차이는?
</a></li>
<li><a href="https://www.youtube.com/watch?v=x-Lp-h_pf9Q&amp;t=365s&amp;ab_channel=%EB%84%90%EB%84%90%ED%95%9C%EA%B0%9C%EB%B0%9C%EC%9E%90TV">Process와 Thread의 차이
</a></li>
<li><a href="https://www.youtube.com/watch?v=1grtWKqTn50&amp;t=723s&amp;ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC">[10분 테코톡] 🌷 코다의 Process vs Thread
</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[OSI 7 계층, 프로토콜]]></title>
            <link>https://velog.io/@juntae_94/OSI-7-%EA%B3%84%EC%B8%B5-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</link>
            <guid>https://velog.io/@juntae_94/OSI-7-%EA%B3%84%EC%B8%B5-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</guid>
            <pubDate>Thu, 20 Jul 2023 13:16:19 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/juntae_94/post/45d6a899-b7e1-405b-8cc6-312750205e22/image.webp" alt=""></p>
<h1 id="네트워크-프로토콜">네트워크 프로토콜</h1>
<blockquote>
<p>네트워크 통신을 하기 위해서 통신에 참여하는 주체들이 따라야 하는 형식, 절차, 규약</p>
</blockquote>
<h1 id="osi-7-layer">OSI 7 Layer</h1>
<blockquote>
<ul>
<li><code>네트워크 프로토콜</code> 기능을 계층구조로 모델링</li>
</ul>
</blockquote>
<ul>
<li>범용적인 네트워크 구조</li>
<li>각 레이어의 프로토콜은 하위 레이어의 프로토콜이 제공하는 기능을 사용하여 동작</li>
</ul>
<h2 id="🤔-왜-사용하는가-">🤔 왜 사용하는가 ?</h2>
<ul>
<li><code>모듈화</code>: 각 계층은 독립적이며 서로 다른 기능을 수행하므로, 하나의 계층의 기능을 개선하거나 변경해도 다른 계층에 영향을 주지 않는다.</li>
<li><code>네트워크 통신의 이해와 표준화</code>: <code>OSI 7 계층</code>의 구조를 통해 네트워크 전문가들이 통신의 원리와 함께 각 계층의 역할과 책임을 더 잘 이해할 수 있으며, 기기 간의 호환성이 폭넓게 보장된다.</li>
<li><code>간편한 문제 해결</code>: 계층화된 구조로 인해 문제 발생 시 해당 부분을 명확하게 파악하고 손쉽게 원인을 찾아 수정할 수 있다.</li>
</ul>
<h2 id="응용-계층-application-layer">응용 계층 (Application Layer)</h2>
<blockquote>
<ul>
<li>사용자 인터페이스와 <code>네트워크를 연결</code>하는 역할을 담당</li>
</ul>
</blockquote>
<ul>
<li>다양한 프로토콜과 응용 프로그램을 지원<ul>
<li><code>HTTP</code> : 웹 사이트를 이용하는 데 사용되는 프로토콜</li>
<li><code>DNS</code> : 도메인 이름과 IP 주소를 매핑해주는 서버</li>
<li><code>SMTP</code> : 메일 전송을 위한 인터넷 표준 통신 프로토콜</li>
<li><code>FTP</code> : 장치간의 파일을 전송하는 데 사용되는 표준 통신 프로토콜</li>
<li><code>SSH</code> : 암호화 네트워크 프로토콜</li>
</ul>
</li>
</ul>
<h2 id="표현-계층-presentation-layer">표현 계층 (Presentation Layer)</h2>
<blockquote>
<ul>
<li>애플리케이션 간의 통신에서 <code>메시지 포맷 관리</code></li>
</ul>
</blockquote>
<ul>
<li>암/복호화 및 압축/해제와 같은 서비스를 제공</li>
</ul>
<h2 id="세션-계층-session-layer">세션 계층 (Session Layer)</h2>
<blockquote>
<ul>
<li>사용자 간의 상호작용 및 서버간의 연결 <code>세션을 관리</code>하고, 연결 유지와 세션 종료를 처리</li>
</ul>
</blockquote>
<h2 id="전송-계층-transport-layer">전송 계층 (Transport Layer)</h2>
<blockquote>
<ul>
<li>애플리케이션 간의 <code>통신</code> 담당</li>
</ul>
</blockquote>
<ul>
<li><p>데이터 전송의 <code>오류 및 흐름</code>을 관리</p>
</li>
<li><p><code>TCP(전송 제어 프로토콜)</code> : 패킷 사이의 순서를 보장하고 연결지향 프로토콜을 사용해 연결, 신뢰성을 구축해서 수신 여부를 확인 (가상회선 패킷 교환 방식)
<img src="https://woovictory.github.io/img/virtual_circut_packet.png" alt=""></p>
</li>
<li><p><code>UDP(사용자 데이터그램 프로토콜)</code> : 순서를 보장하지 않고 수신 여부를 확인하지 않으며 단순히 데이터만 주는 프로토콜 (데이터그램 패킷 교환 방식)
<img src="https://woovictory.github.io/img/datagram_packet.png" alt=""></p>
</li>
</ul>
<h2 id="네트워크-계층-network-layer">네트워크 계층 (Network Layer)</h2>
<blockquote>
<ul>
<li>다른 네트워크와의 원활한 데이터 전송을 위해 <code>IP 주소</code> 등의 라우팅 및 경로 설정을 담당(<code>데이터 전송</code>)</li>
</ul>
</blockquote>
<ul>
<li>네트워크 간의 최적의 경로 설정</li>
</ul>
<h2 id="데이터-링크-계층-data-link-layer">데이터 링크 계층 (Data Link Layer)</h2>
<blockquote>
<ul>
<li>인접한 노드 간의 <code>통신</code> 담당</li>
</ul>
</blockquote>
<ul>
<li>MAC 주소기반 통신<ul>
<li>IP 주소 -&gt; MAC 주소 (<code>ARP</code> 프로토콜)</li>
<li>MAC 주소 -&gt; IP 주소 (<code>RARP</code> 프로토콜)</li>
</ul>
</li>
</ul>
<h2 id="물리-계층-physical-layer">물리 계층 (Physical Layer)</h2>
<blockquote>
<ul>
<li><code>비트 단위</code>의 데이터를 전송하는 데 사용되는 하드웨어와 기초적인 연결 방식을 정의</li>
</ul>
</blockquote>
<h1 id="📎-참고자료">📎 참고자료</h1>
<ul>
<li><a href="https://woovictory.github.io/2018/12/28/Network-Packet-Switching-Method/">[네트워크] 가상회선 패킷 교환 vs 데이터그램 패킷 교환</a></li>
<li><a href="https://search.shopping.naver.com/book/catalog/32478035848?cat_id=50010920&amp;frm=PBOKMOD&amp;query=%EB%A9%B4%EC%A0%91%EC%9D%84+%EC%9C%84%ED%95%9C+CS+%EC%A0%84%EA%B3%B5%EC%A7%80%EC%8B%9D+%EB%85%B8%ED%8A%B8&amp;NaPm=ct%3Dlkb5mzco%7Cci%3D92fe3a6777faadcf59fcfa77db0d6644a9b7dac1%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3D31b7e0d0add872b682e4facbe1f1f4ddb3e44fa0">면접을 위한 CS 전공지식 노트 - 주홍철</a></li>
<li><a href="https://www.youtube.com/watch?v=w903b3QLkrQ&amp;ab_channel=%ED%9D%A5%EB%8B%AC%EC%8C%A4">[Q&amp;A] 네트워크 | OSI 7계층 - 홍달쌤</a></li>
<li><a href="https://www.youtube.com/watch?v=6l7xP7AnB64&amp;t=649s&amp;ab_channel=%EC%89%AC%EC%9A%B4%EC%BD%94%EB%93%9C">[입문용] 프로토콜과 OSI 7 layer 설명! 네트워크의 기능들이 어떻게 구조화 돼서 동작하는지를 설명합니다! 👍 - 쉬운코드</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[GoodBye 멋사]]></title>
            <link>https://velog.io/@juntae_94/%ED%95%99%EC%83%9D%EC%97%90%EC%84%9C-%EC%9D%B4%EC%A0%9C-%EC%82%AC%ED%9A%8C%EB%A1%9C</link>
            <guid>https://velog.io/@juntae_94/%ED%95%99%EC%83%9D%EC%97%90%EC%84%9C-%EC%9D%B4%EC%A0%9C-%EC%82%AC%ED%9A%8C%EB%A1%9C</guid>
            <pubDate>Fri, 14 Jul 2023 23:39:27 GMT</pubDate>
            <description><![CDATA[<p><img src="https://oopy.lazyrockets.com/api/v2/notion/image?src=https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fe9408110-f8f4-4f47-8e48-2a369303862e%2Fbackendschool_2_OG_front.png&blockId=1a43ed14-6267-44b9-afc6-8ba9891dcd02" alt=""></p>
<h1 id="😌-졸업">😌 졸업</h1>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/8b68bd40-866d-407b-ad87-fd1142115880/image.png" alt=""></p>
<blockquote>
<p>5개월 동안 <code>멋쟁이 사자처럼 백엔드 스쿨 3기</code> 학습과정을 어제 마쳤다. 
아직 까지는 실감이 나질 않는다. 이제 진짜 시작이라는 느낌이 강하게 든다. 
짧다면 짧고 길다면 긴 시간이 지나 좋은 사람들도 많이 사귀었다. 
많이 배우고 많이 성장할 수 있는 기간이었다. 이제 취업이라니...</p>
</blockquote>
<p><img src="https://t1.daumcdn.net/cfile/tistory/995B744A5C474A5907" alt=""></p>
<h1 id="😁-앞으로-계획">😁 앞으로 계획</h1>
<h2 id="🐻-알고리즘-공부">🐻 알고리즘 공부</h2>
<blockquote>
<p>알고리즘 공부를 꾸준히 해야겠다. 꾸준하게 공부를 해야 할 부분인 것 같다. 
나의 최종 목표인 <code>대기업</code>을 가기 위해서는 알고리즘은 필수이기 때문에 길게 꾸준히 공부를 할 생각이다. 우선 하루에 2문제 정도 꾸준히 풀려고 노력할 것!!</p>
</blockquote>
<h2 id="🐼-cs공부">🐼 CS공부</h2>
<blockquote>
<p>비전공자이기 때문에 CS 공부가 부족한건 현실이다.
이 부분을 인정하고 전공자처럼 비슷한 수준이 되기 위해서는 꾸준한 학습이 필요하다. 유튜브 &amp; 강의 &amp; 도서를 통해서 꾸준한 학습을 할 예정이다.</p>
</blockquote>
<h2 id="🐹-1차-2차-프로젝트-리펙토링">🐹 1차, 2차 프로젝트 리펙토링</h2>
<blockquote>
<p>프로젝트를 함으로써 많이 부족한 부분이 많았다. 
강사님들의 피드백도 많이 받았고 지금에서야 다시 보면 수정이 필요한 부분이 더럿 보인다. 
또한 이력서를 지원할 때 포트폴리오도 중요하기 때문에 팀원들과 프로젝트를 리펙토링 할 계획이다. 또한 <code>스프링부트</code>, <code>JPA</code>를 더 학습을 병행할 계획이다.</p>
</blockquote>
<h2 id="🐱-취업준비">🐱 취업준비</h2>
<blockquote>
<p>우선 지금 제일 중요한 부분이 취업이다. 교육기간이 끝나고 강사님의 <code>교육수료 후 10 계명</code>에서 많은 것을 느꼈다. 혼자서 공부하는 것도 좋지만 실무에서 배우는 게 제일 좋다고 하셨다. 강사님이 말한 것처럼 <code>취업을 위해서 나는 아직 더 공부해야 한다</code>라는 생각이 강했는데 우선 취업을 준비하면서 부딪혀 볼 생각이다.</p>
</blockquote>
<ul>
<li>하루에 30~1시간 정도 채용공고 확인하기<ul>
<li>나는 <code>음악</code>을 좋아해서 <code>음악</code>관련 회사에 가고 싶다.</li>
<li>SI 보다는 스타트업에 가고싶다.</li>
</ul>
</li>
<li>이력서, 자소서 다듬기<ul>
<li>첫 이력서, 자소서다 보니 많이 부족하다. 그래서 계속 보완을 해야겠다.</li>
</ul>
</li>
</ul>
<h1 id="🥲-끝으로">🥲 끝으로..</h1>
<blockquote>
<p>멋쟁이사자처럼의 품을 떠나 이제 홀로서기를 해야 할 시간이다. 
짧았던 5개월 동안 스스로 많이 발전하게 된 시간이었다.
이제 취업을 해야해서 걱정이 되지만...무엇보다 좋은 사람들을 만나게 돼서 너무 좋았다. 
같이 <code>알고리즘을 공부했던 스터디원</code>, <code>1차 프로젝트 팀원</code>, <code>2차 프로젝트 팀원</code> 그 외 궁금한 점을 서로 공유했던 <code>훈련생들</code> 그리고 5개월 동안 좋은 교육을 준비를 해주신 <code>강사님</code>, <code>특별강사님</code>, <code>멘토님</code> 마지막으로 운영에 힘써주신 <code>매니저님들</code> 전부 만나서 너무 좋았다. 혼자였으면 힘들었겠지만 같이 함께해서 좋은 결과로 끝을 맺을 수 있었다. 다들 각자의 위치해서 열심히 해서 모두 행복했으면 좋겠다. 
끝으로 내가 제일 좋아하는 <code>Juice Wrld</code>의 명언으로 마무리..</p>
</blockquote>
<blockquote>
<p><code>&quot;The goal in life is not to live forever but to create something that will - Jucie  Wrld&quot;</code></p>
</blockquote>
<h2 id="자-취업-드가자">자~ 취업 드가자</h2>
<p><img src="https://i1.ruliweb.com/ori/21/12/30/17e0ba460f417fc3a.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Jira 이용 가이드]]></title>
            <link>https://velog.io/@juntae_94/Jira-%EC%9D%B4%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
            <guid>https://velog.io/@juntae_94/Jira-%EC%9D%B4%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9C</guid>
            <pubDate>Sat, 08 Jul 2023 13:12:07 GMT</pubDate>
            <description><![CDATA[<h1 id="jira-가이드-라인">Jira 가이드 라인</h1>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/ec6ba525-9264-428a-887e-1087048db8da/image.png" alt=""></p>
<h2 id="jira가-뭘까-">Jira가 뭘까 ?</h2>
<ul>
<li>프로젝트 관리를 위한 강력한 이슈 추적 도구로, 팀의 업무를 조직화하고 추적하며 원활한 협업업무를 제공한다.</li>
</ul>
<h2 id="jira의-핵심-기능과-개념">Jira의 핵심 기능과 개념</h2>
<h3 id="프로젝트project">프로젝트(Project)</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/a06152fa-e84e-42d5-a57f-76a1263858ed/image.png" alt=""></p>
<ul>
<li>JIRA에서 프로젝트 단위로 이슈를 관리하는 공간</li>
<li>각 프로젝트마다 독립된 설정값을 따르며 이슈키의 ID도 다른 형태로 생성</li>
</ul>
<h3 id="이슈issue">이슈(Issue)</h3>
<ul>
<li>보드 내 생성된 작업들을 이슈라고 한다.</li>
<li>크게 <code>Epic</code>, <code>Story</code>, <code>Task</code>, <code>Bug</code>, <code>Sub-Task</code>를 기본적으로 사용</li>
<li>팀이 <code>작업의 상태</code>와 <code>진행 상황</code>을 파악할 수 있도록 도와준다.</li>
</ul>
<h4 id="이슈-키">이슈 키</h4>
<ul>
<li>Jira로 추적하는 모든 작업에 대한 고유 식별자</li>
<li><code>GitHub</code> 와 연동하여 <code>Commit</code> , <code>Branch</code> , <code>PR</code> 등등 활용가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/51f8e1f0-9280-4a7a-9852-415f5376354f/image.png" alt=""></p>
<ol>
<li>프로젝트 키</li>
<li>일련 번호</li>
</ol>
<h3 id="에픽epic">에픽(Epic)</h3>
<ul>
<li>스프린트를 거쳐 완료되는 정도의 작업량을 가진 업무</li>
<li><code>Stroy</code>들을 묶은 상위 개념의 기능을 의미</li>
<li>기능에 대한 정의만하지 상세한 기술은 <code>Stroy</code>를 통해 설명</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/53110638-0f76-4f6b-ab5c-ba04d5960b73/image.png" alt=""></p>
<h3 id="스토리story">스토리(Story)</h3>
<ul>
<li>최소 단위의 <code>요구사항</code>을 말한다.</li>
<li>하나의 <code>Epic</code>에 여러개의 <code>Stroy</code> 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/96f89e60-46c2-4d1a-922f-0468ab3e3bd3/image.png" alt=""></p>
<h3 id="태스크task">태스크(Task)</h3>
<ul>
<li>하나의 스토리를 완성하기 위한 구체적인 작업들<ul>
<li>디자인</li>
<li>기술검토</li>
<li>개발</li>
<li>문서화</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/578a7f16-0d92-4e85-983f-1797eaf06069/image.png" alt=""></p>
<ul>
<li><code>Story</code> 를 눌러 <code>하위 이슈 추가</code> 버튼 클릭</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/fffa34ff-0049-4585-b371-8b5bec6d51bc/image.png" alt=""></p>
<h2 id="백로그">백로그</h2>
<ul>
<li>일반적으로 팀이 프로젝트에서 수행할 작업 (해야 할일들의 목록)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/512cd385-3475-4340-b893-8d666437f32a/image.png" alt=""></p>
<ol>
<li><strong>백로그 :</strong> 백로그의 현재 문제 목록입니다(여기에 몇 가지 문제가 표시되어 어떻게 표시되는지 알 수 있습니다).</li>
<li><strong>이슈 상세 보기 :</strong> 현재 선택된 이슈의 상세 보기입니다.</li>
</ol>
<h2 id="이슈-만들기">이슈 만들기</h2>
<h3 id="로드맵-탭에서-만들기-에픽-클릭">로드맵 탭에서 <code>만들기 에픽</code> 클릭</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/c69bd6fa-ec2a-48bf-9b27-83c78e62df5d/image.png" alt=""></p>
<ul>
<li>ex) <code>HAPPY-44 게시판 관련 기능 구현</code> 작업 예시</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/a88aede2-ff3d-4c6f-891e-b3e0b71824fb/image.png" alt=""></p>
<h3 id="에픽-생성후-하위-스토리-생성">에픽 생성후 하위 스토리 생성</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/53175e20-4405-4cce-89eb-261b0e4a920b/image.png" alt=""></p>
<ul>
<li>해당 스토리 자세히 보기 / 수정도 가능</li>
</ul>
<h3 id="백로그-탭에서-스토리-추가-확인-가능">백로그 탭에서 스토리 추가 확인 가능</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/e4eaa81f-c621-49e6-8f87-12f4decb236e/image.png" alt=""></p>
<h3 id="백로그-탭에서-이슈-생성가능-하지만-따로-에픽스토리-설정해줘야함">백로그 탭에서 이슈 생성가능 하지만 따로 에픽,스토리 설정해줘야함</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/3308c6cb-7313-4495-b373-bb92fb12cfeb/image.png" alt=""></p>
<h2 id="스프린트">스프린트</h2>
<ul>
<li>백로그에서 작업을 완료하는 고정된 기간</li>
</ul>
<h2 id="스프린트-만들기">스프린트 만들기</h2>
<h3 id="백로그-탭으로-이동후-스프린트-만들기-클릭">백로그 탭으로 이동후 <code>스프린트 만들기</code> 클릭</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/b6e08fbf-1021-408f-88a6-5ea694a20ceb/image.png" alt=""></p>
<h3 id="해당-스프린트에-대한-내용-기입">해당 스프린트에 대한 내용 기입</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/b9ac88b5-70be-4ff3-9fd9-8b55c02e49c5/image.png" alt=""></p>
<h3 id="해당-스프린트에-수행할-백로그-이동drag후-스프린트-시작">해당 스프린트에 수행할 백로그 이동(Drag)후 스프린트 시작</h3>
<ul>
<li>해당 스프린트는 2주차 기능구현으로 예시를 듦</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/ea4bf648-eef6-4c53-b76e-662baee5aea2/image.png" alt=""></p>
<h3 id="보드-탭에서-해당-스프린트-별-내용-확인-가능">보드 탭에서 해당 스프린트 별 내용 확인 가능</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/a5985dad-c381-42d5-91c8-077694abad0d/image.png" alt=""></p>
<h3 id="로드맵-탭에서도-해당-스프린트-내용-확인-가능">로드맵 탭에서도 해당 스프린트 내용 확인 가능</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/e536799a-396f-4ce4-9aca-124009711755/image.png" alt=""></p>
<h1 id="jira와-github-연동-작업">Jira와 GitHub 연동 작업</h1>
<h2 id="작업할-이슈를-선택">작업할 이슈를 선택</h2>
<ul>
<li>ex) 이슈코드 <code>HAPPY-43</code> 작업</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/961dcd02-5cfa-49d4-a9ab-4cb10eb99844/image.png" alt=""></p>
<h2 id="해당-이슈에-대한-branch-생성">해당 이슈에 대한 <code>Branch</code> 생성</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/1fdf7673-b0e8-490a-a30c-a1c3db548409/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/751f73a0-804e-4714-b6ef-f16046a43733/image.png" alt=""></p>
<ul>
<li><code>Repository</code> / <code>Branch from</code> / <code>Branch name</code> 설정</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/dbcda97b-8ce6-4227-a272-56760a789dbe/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/f777ba6a-c4e8-4917-aabc-f1b5971efaba/image.png" alt=""></p>
<ul>
<li>해당 이슈코드로 <code>Branch</code> 가 생성된 것을 볼 수 있다.</li>
</ul>
<h2 id="해당-branch-에서-작업-커밋-메시지에-이슈코드-삽입-x">해당 <code>Branch</code> 에서 작업 (커밋 메시지에 이슈코드 삽입 X)</h2>
<ul>
<li><a href="https://www.notion.so/Git-Convention-ca7c8b09a1c0414188d6375954dd0523?pvs=21">Git Convention</a> 을 지키며 메시지 작성</li>
<li>ex) 작업 예시 md파일 수정</li>
</ul>
<h2 id="ide-에서-원격으로-생성된-브런치-가져오기">IDE 에서 원격으로 생성된 브런치 가져오기</h2>
<ul>
<li><code>해당 내용은 위에서 사용하는 이슈코드 HAPPY-43 이 아닌 다른 걸로 진행됩니다</code></li>
<li><code>제가 실수로 HAPPY-43을 이미 머지를 해버려서...</code></li>
</ul>
<h3 id="원격-branch명-확인">원격 <code>Branch명 확인</code></h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/9a0acb80-73ca-481d-ada6-49361da9477d/image.png" alt=""></p>
<h3 id="ide-터미널에서-git-fetch-입력해서-원격-브런치-가져오기">IDE 터미널에서 <code>git fetch</code> 입력해서 원격 브런치 가져오기</h3>
<p>git fetch --prune</p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/cde67e37-0888-43f0-b467-d2dcf30a34dd/image.png" alt=""></p>
<h3 id="가져온-브런치-확인-git-branch--r">가져온 브런치 확인 <code>git branch -r</code></h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/19bae01e-554c-4f0a-bcb4-11ce1280a988/image.png" alt=""></p>
<h3 id="브런치-변경-git-checkout-happy-119">브런치 변경 <code>git checkout HAPPY-119</code></h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/edf11385-15ca-4b8d-a7ef-0826b6757478/image.png" alt=""></p>
<h2 id="branch-pr생성"><code>Branch</code> <code>PR</code>생성</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/e0d57514-fb51-4bf3-a0cc-7fe58a80e73c/image.png" alt=""></p>
<h2 id="해당-pr-제목은-이슈코드를-제외-한-기능-이름-사용">해당 <code>PR</code> 제목은 <code>이슈코드를 제외</code> 한 기능 이름 사용</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/c0f24355-086c-4b4d-9c71-0eb8cade50f4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/a99f911c-8b90-4b60-8b26-c00cfc662bce/image.png" alt=""></p>
<h2 id="jira에서-branch--pr-확인-가능">Jira에서 <code>Branch</code> , <code>PR</code> 확인 가능</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/46a62d74-c13c-43c5-8a26-48f87bf3428b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/d7b50c43-95b8-4318-b9c7-80303e7e603d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/011322da-2c50-40c1-96fd-d970c5a217c0/image.png" alt=""></p>
<h2 id="해당-branch-작업-종료후-merge">해당 <code>Branch</code> 작업 종료후 <code>Merge</code></h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/00b78e99-35c8-4e04-83dd-c39909d5489c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/9c41f314-6a26-4072-822b-8004f6421aea/image.png" alt=""></p>
<h2 id="jira에서-merge-확인">Jira에서 <code>Merge</code> 확인</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/6b22a993-5625-45ab-842e-392cde9b2ae8/image.png" alt=""></p>
<h2 id="jira에서-workflow-수정">Jira에서 WorkFlow 수정</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/f67a9a27-130a-4e1f-a231-4fc075760386/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 부트 자동 생성자 올바르게 사용하기]]></title>
            <link>https://velog.io/@juntae_94/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%EC%9E%90%EB%8F%99-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%83%9D%EC%84%B1-%EC%A3%BC%EC%9D%98-%EC%82%AC%ED%95%AD</link>
            <guid>https://velog.io/@juntae_94/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%EC%9E%90%EB%8F%99-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%83%9D%EC%84%B1-%EC%A3%BC%EC%9D%98-%EC%82%AC%ED%95%AD</guid>
            <pubDate>Wed, 21 Jun 2023 07:57:24 GMT</pubDate>
            <description><![CDATA[<h1 id="생성자-자동-생성자-올바르게-사용하기">생성자 자동 생성자 올바르게 사용하기</h1>
<ul>
<li>우선 <code>Lombok</code>에서 제공하는 어노테이션 3개를 떠올릴 수 있다.<h2 id="noargsconstructor">@NoArgsConstructor</h2>
</li>
<li>매개변수가 없는 기본 생성자를 자동으로 생성</li>
<li><code>JPA</code>에서는 프록시를 생성을 위해서 기본 생성자를 반드시 하나를 생성해야한다.<pre><code class="language-java">@NoArgsConstructor
public class Example {
  private String field;
}
</code></pre>
</li>
</ul>
<p>↓</p>
<p>public class Example {
    private String field;</p>
<pre><code>public Example() {
}</code></pre><p>}</p>
<pre><code>## @AllArgsConstructor
- 모든 필드를 매개변수로 받는 생성자를 자동으로 생성
- 매우 편리하게 생성자를 만들어주지만, 별 생각없이 작성한 코드가 치명적인 버그를 만들어낼 수도 있다.
```java
@AllArgsConstructor
public class Example {
    private String field;
}

↓

public class Example {
    private String field;

    public Example(String field) {
        this.field = field;
    }
}</code></pre><h2 id="requiredargsconstructor">@RequiredArgsConstructor</h2>
<ul>
<li>필드 중 초기값이 할당되지 않은 <code>final</code> 필드, 그리고 <code>@NonNull</code> 어노테이션으로 표시된 필드를 매개변수로 받는 생성자를 자동으로 생성<pre><code class="language-java">@RequiredArgsConstructor
public class Example {
  private final String field1;
  @NonNull
  private String field2;
}
</code></pre>
</li>
</ul>
<p>↓</p>
<p>public class Example {
    private final String field1;
    private String field2;</p>
<pre><code>public Example(String field1, String field2) {
    if (field2 == null) {
      throw new NullPointerException(&quot;field2 is marked non-null but is null&quot;);
    }
    this.field1 = field1;
    this.field2 = field2;
}</code></pre><p>}</p>
<pre><code>
## 결론
- 물론 편하게 위 생성자를 사용해서 생성자를 만드는것도 좋지만, **_사소한 객체 생성부터 고민해보는 것이 클린 코드, 유지 보수를 고려한 좋은 코드를 만들 수 있는 습관이 된다고_** 한다.
- 최대한 `@RequiredArgsConstructor`, `@AllArgsConstructor`사용을 지양하며 `@NoArgsConstructor`에 생성자의 접근레벨을 `PROTECTED`로 해준뒤 생성자를 생성할경우 `@Builder`를 붙여주는 방향으로 해야겠다.
```java
// refactor 전 코드 
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReviewImage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long Id;
    @ManyToOne
    private Review review;
    @NotNull
    private String imageUrl;
}

// refactor 후 코드
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CommentImage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long Id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = &quot;comment_id&quot;)
    private Comment comment;
    @NotNull
    private String imageUrl;

    @Builder
    public CommentImage(Comment comment, String imageUrl) {
        this.comment = comment;
        this.imageUrl = imageUrl;
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[DB테이블 자동생성]]></title>
            <link>https://velog.io/@juntae_94/DB%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%9E%90%EB%8F%99%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@juntae_94/DB%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%9E%90%EB%8F%99%EC%83%9D%EC%84%B1</guid>
            <pubDate>Sun, 28 May 2023 07:52:23 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/6de022a1-f534-486b-8daa-2c8cb0766489/image.png" alt="">
<img src="https://velog.velcdn.com/images/juntae_94/post/5f27a319-bfb3-4d2b-91fd-fd8b713c41fe/image.png" alt=""></p>
<ul>
<li>엔티티를 생성해줬음에도 <code>DB</code>에서는 아무런 정보를 찾을수 없었다.</li>
</ul>
<h1 id="문제-해결">문제 해결</h1>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/6ea4ec91-6a77-4e4d-92ce-a28a9cf3b91f/image.png" alt=""></p>
<ul>
<li><code>application.yml</code>에서 따로 설정을 해주어야 한다.<blockquote>
<p><code>jpa</code>: <code>JPA(Java Persistence API)</code>에 대한 설정을 지정하는 섹션
<code>hibernate</code>: <code>Hibernate ORM(Object-Relational Mapping)</code>에 대한 설정을 지정하는 섹션입니다. <code>Hibernate</code>는 <code>JPA</code>의 구현체 중 하나로 많이 사용됩니다.
<code>ddl-auto</code>: 데이터베이스 스키마의 생성 및 변경 방법을 설정
<code>create</code>: 애플리케이션 시작 시 매번 데이터베이스 스키마를 새로 생성</p>
</blockquote>
</li>
</ul>
<h1 id="회고">회고</h1>
<blockquote>
<p>이것 또한 엄청 초보적인 실수를 저지르고 말았다.
다음에는 똑같은 실수를 하지 않겠습니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[LocalDateTime 자동 추적]]></title>
            <link>https://velog.io/@juntae_94/LocalDateTime-%EC%9E%90%EB%8F%99-%EC%B6%94%EC%A0%81</link>
            <guid>https://velog.io/@juntae_94/LocalDateTime-%EC%9E%90%EB%8F%99-%EC%B6%94%EC%A0%81</guid>
            <pubDate>Sun, 28 May 2023 07:47:00 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/juntae_94/post/3ffa7f87-f3f5-48f5-b6a2-94d8824b425b/image.png" alt=""></p>
<h1 id="문제">문제</h1>
<ul>
<li>위 사진과 같이 <code>@CreatedDate</code>, <code>@LastModifiedDate</code>를 어노테이션을 사용을 했음에도 DB에는 <code>null</code>값이 저장이 되었다.
<img src="https://velog.velcdn.com/images/juntae_94/post/0d276e98-bf6a-4a94-9d4c-67ec2a530ee5/image.png" alt=""></li>
</ul>
<h1 id="문제-해결">문제 해결</h1>
<ul>
<li><code>@CreatedDate</code>, <code>@LastModifiedDate</code> 어노테이션이 활성화 되기 위해서는 <code>@EnableJpaAuditing</code> 을 붙여 주어야 한다.</li>
<li><code>@EnableJpaAuditing</code> : <code>Spring Data JPA</code>에서 제공하는 기능으로, <code>JPA</code> 엔티티에 대한 감사(<code>Auditing</code>) 기능을 활성화하는 데 사용됩니다. 감사 기능을 활성화하면 엔티티의 생성일(<code>created date</code>) 및 수정일(<code>modified date</code>)을 자동으로 추적할 수 있습니다.
<img src="https://velog.velcdn.com/images/juntae_94/post/c684efed-f1df-4892-a687-e59ae4118322/image.png" alt="">
<img src="https://velog.velcdn.com/images/juntae_94/post/b5f5f7fa-d3c9-4e2d-ab6a-267ca9ed27bb/image.png" alt=""></li>
</ul>
<h1 id="회고">회고</h1>
<blockquote>
<p>이렇게 간단한 문제로 시간을 잡아 먹혔다는 것을 조금 반성을 해야겠다.
다음부터는 똑같은 실수는 일어나지 않을것같다. 충격 그 자체</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[카카오, 구글 API를 활용해서 로그인 기능 구현에 문제]]></title>
            <link>https://velog.io/@juntae_94/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B5%AC%EA%B8%80-API%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%B4%EC%84%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%EC%97%90-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@juntae_94/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B5%AC%EA%B8%80-API%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%B4%EC%84%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%EC%97%90-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Sun, 28 May 2023 07:34:22 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-내용">문제 내용</h1>
<ul>
<li>구글 API를 활용해서 소셜로그인 기능을 구현을 했다.<pre><code class="language-java">  @Column(unique = true)
  private String username;
  private String password;
  private String name;
  @Column(unique = true)
  private String nickName;
  @Column(unique = true)
  private String email;
  @Builder.Default
  private String role = &quot;user&quot;;
  private String providerTypeCode;</code></pre>
<pre><code class="language-java">//MemberService
Member member = Member
              .builder()
              .providerTypeCode(providerTypeCode)
              .username(username)
              .password(password)
              .name(name)
              .nickName(nickName)
              .email(email)
              .build();</code></pre>
</li>
<li>에러내용<blockquote>
<ul>
<li>에러내용
There was an unexpected error (type=Internal Server Error, status=500).
could not execute statement; SQL [n/a]; constraint [member.UK_mbmcqelty0fbrvxp1q58dn57t]
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [member.UK_mbmcqelty0fbrvxp1q58dn57t]</li>
</ul>
</blockquote>
</li>
</ul>
<ul>
<li><p>이런 에러가 발생했다. </p>
</li>
<li><p>GPT에게 문의 한 답변</p>
<blockquote>
<p>해당 에러는 내부 서버 오류(Internal Server Error)로, 데이터 무결성(Data Integrity) 제약조건 위반으로 인해 SQL 문장을 실행할 수 없음을 나타냅니다. 보다 구체적으로는 &quot;member.UK_mbmcqelty0fbrvxp1q58dn57t&quot; 제약조건이 위반되었음을 알려줍니다.
이 에러는 주로 데이터베이스 시스템에서 발생하는데, 일반적으로 테이블에 대해 고유한(unique) 제약조건이 설정되어 있는 경우, 그 제약조건을 위반하는 데이터를 삽입하려고 할 때 발생할 수 있습니다.</p>
</blockquote>
</li>
<li><p>그래서 혹시 뭐가 문제인지 하나씩 빼고 실행을 해보니 <code>nickName</code>, <code>email</code>에서 문제가 발생했다. 아마 원인이 <code>@Column(unique = true)</code> 를 설정해줘서 <code>join()</code>에 <code>&quot;&quot;</code> 값을 넣어서 저장해서 원인이 발생한듯 했다.</p>
</li>
</ul>
<h1 id="문제-해결-방법">문제 해결 방법</h1>
<ol>
<li>우선 첫번째 방법으로는 <code>nickName</code>, <code>email</code>에 <code>@Column(unique = true)</code> 값을 제거 해주면 정상 작동하였다.</li>
</ol>
<ul>
<li>하지만 이번 프로젝트에서는 <code>nickName</code>, <code>email</code> 값이 유니크해야 하므로 이방법은 패스 하게 되었다.</li>
</ul>
<ol start="2">
<li>두번째 방법으로는 <code>join()</code>메소드에 <code>&quot;&quot;</code>값을 넣어주는 것이 아닌 <code>null</code>을 넣어주는 방법으로 해결하였다.</li>
</ol>
<h1 id="문제에-대한-궁금증">문제에 대한 궁금증</h1>
<ul>
<li><p>이러한 에러가 발생한 이유가 뭘까 ?</p>
<ul>
<li><code>email</code>, <code>nickName</code>의 값을 <code>unique</code>로 설정해주었지만 소셜로그인을 하게 되면 전부다 <code>&quot;&quot;</code>로 저장되기 때문에 같은 값을 저장해서 원인이 발생했다.</li>
</ul>
</li>
<li><p>이렇게 해결하는게 최선의 방법일까 ?</p>
<ul>
<li>추후 업데이트 예정</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[젠킨스,도커를 사용해 지속적인 배포 진행하기]]></title>
            <link>https://velog.io/@juntae_94/%EC%A0%A0%ED%82%A8%EC%8A%A4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EC%9E%90%EB%8F%99%EB%B0%B0%ED%8F%AC%EC%A7%84%ED%96%89%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@juntae_94/%EC%A0%A0%ED%82%A8%EC%8A%A4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EC%9E%90%EB%8F%99%EB%B0%B0%ED%8F%AC%EC%A7%84%ED%96%89%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 15 May 2023 13:44:41 GMT</pubDate>
            <description><![CDATA[<h1 id="젠킨스">젠킨스</h1>
<h2 id="네이버-클라우드-플랫폼에서-포트-열어주기">네이버 클라우드 플랫폼에서 포트 열어주기</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/a420d7ff-ffc5-4079-9180-aa6a54b1c7a3/image.png" alt=""></p>
<h2 id="젠킨스-설치하기">젠킨스 설치하기</h2>
<ul>
<li>열어 주었던 <code>8081</code>포트에 설치<pre><code class="language-bash">docker run \\
--name jenkins_1 \\
-p 8081:8080 \\
-e TZ=Asia/Seoul \\
-v /docker_projects/jenkins_1/var/jenkins_home:/var/jenkins_home \\
-v /var/run/docker.sock:/var/run/docker.sock \\
-v /docker_projects/jenkins_1/data:/data \\
-u root \\
-d \\
--restart unless-stopped \\
jenkins/jenkins:lts</code></pre>
</li>
<li><code>--name jenkins_1</code> : 컨테이너의 이름을 <code>&quot;jenkins_1&quot;</code>로 지정</li>
<li><code>-p 8081:8080</code> : 호스트의 8081 포트와 컨테이너의 8080 포트를 매핑</li>
<li><code>-e TZ=Asia/Seoul</code> : 컨테이너 내부에서 사용할 타임존을 &quot;Asia/Seoul&quot;로 설정 </li>
<li><code>-v docker_projects/jenkins_1/var/jenkins_home:/var/jenkins_home</code> : 호스트의 /docker_projects/jenkins_1/var/jenkins_home 경로와 컨테이너의 /var/jenkins_home 경로를 볼륨 매핑 / Jenkins 설정과 데이터를 영구적으로 보관</li>
<li><code>-v /var/run/docker.sock:/var/run/docker.sock</code> : 호스트의 Docker 소켓 파일(/var/run/docker.sock)을 컨테이너 내부의 동일한 경로에 바인드 (Docker 명령을 컨테이너에서 실행가능)</li>
<li><code>-v /docker_projects/jenkins_1/data:/data</code> : 호스트의 /docker_projects/jenkins_1/data 경로와 컨테이너의 /data 경로를 볼륨 매핑 / Jenkins 작업 데이터를 영구적으로 보관</li>
<li><code>-u root</code>: 컨테이너 내부에서 root 사용자로 실행</li>
<li><code>-d</code>: 컨테이너를 백그라운드에서 실행 (데몬)</li>
<li><code>--restart unless-stopped</code> : 컨테이너가 비정상적으로 종료되었을 때 자동으로 재시작</li>
<li><code>jenkins/jenkins:lts</code> : 사용할 Docker 이미지를 jenkins/jenkins:lts로 지정<h2 id="젠킨스-로그인">젠킨스 로그인</h2>
</li>
</ul>
<h3 id="초기-비밀번호-확인">초기 비밀번호 확인</h3>
<pre><code class="language-bash">docker exec jenkins_1 cat /var/jenkins_home/secrets/initialAdminPassword</code></pre>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/3f326ce6-fc8e-4e39-91dc-99ae2b048ffe/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/d9ac3b15-a88e-4bf5-ad9a-cf77d6ca150c/image.png" alt=""></p>
<h2 id="jdk-update">JDK Update</h2>
<pre><code class="language-bash"># jenkins_1 컨테이너 내부로 들어가서 작업을 수행
docker exec -it jenkins_1 bash

# 패키지 관리자인 apt를 사용하여 패키지 목록을 최신 상태로 업데이트
apt-get update

# 컨테이너 내부에서 openjdk-17-jdk 패키지를 설치
apt-get install openjdk-17-jdk -y</code></pre>
<h2 id="젠킨스-컨테이너-내에-docker-설치">젠킨스 컨테이너 내에 Docker 설치</h2>
<pre><code class="language-bash"># jenkins_1 bash 접속
docker exec -it jenkins_1 bash
</code></pre>
<pre><code class="language-bash">apt-get update -y
apt-get install -y ca-certificates curl gnupg lsb-release
mkdir -p /etc/apt/keyrings
rm /etc/apt/keyrings/docker.gpg
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo &quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable&quot; | tee /etc/apt/sources.list.d/docker.list &gt; /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli docker-compose-plugin</code></pre>
<ul>
<li><code>apt-get update -y</code> : 패키지 업데이트</li>
<li><code>apt-get install -y ca-certificates curl gnupg lsb-release</code> : <code>Docker</code> 설치를 위해 종속성 패키지 설치</li>
<li><code>mkdir -p /etc/apt/keyrings</code> : <code>/etc/apt/keyrings</code> 경로에 디렉토리를 생성 (<code>APT</code> 패키지 매니저의 <code>키링(keyring)</code> 파일을 저장하기 위한 공간)</li>
<li><code>rm /etc/apt/keyrings/docker.gpg</code> : <code>/etc/apt/keyrings/docker.gpg</code> 파일을 삭제 (<code>Docker</code>의 공식 <code>GPG</code> 키를 저장하기 위한 용도)</li>
<li><code>curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg</code> : <code>Docker</code>의 공식 <code>GPG</code> 키를 다운로드하여 <code>/etc/apt/keyrings/docker.gpg</code> 파일로 저장(<code>GPG</code> 키는 <code>APT</code>가 <code>Docker</code>의 패키지를 신뢰할 수 있는지 확인하는 데 사용)</li>
<li><code>echo &quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable&quot; | tee /etc/apt/sources.list.d/docker.list &gt; /dev/null</code> : <code>Docker</code>의 <code>APT</code> 저장소 정보를 <code>/etc/apt/sources.list.d/docker.list</code> 파일에 저장 (<code>Docker</code> 관련 패키지를 설치)</li>
<li><code>apt-get update</code> : 패키지 업데이트</li>
<li><code>apt-get install -y docker-ce docker-ce-cli docker-compose-plugin</code> : <code>Docker</code>와 <code>Docker Engine</code> 및 <code>Docker Compose</code>의 구성 요소 설치</li>
</ul>
<h2 id="젠킨스에서-pipeline-생성">젠킨스에서 Pipeline 생성</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/6458af34-5139-4f7c-80d3-66baef6e52b2/image.png" alt=""></p>
<h3 id="credentials을-이용해-secretyml-자동-업로드">Credentials을 이용해 secret.yml 자동 업로드</h3>
<ul>
<li>Credentials : 보안 관련 정보를 저장하고 관리하기 위한 기능</li>
<li>원격 Git 저장소에서 코드를 가져올 때 인증 정보를 사용하거나, 도커 레지스트리에 이미지를 푸시할 때 인증 정보를 사용
<img src="https://velog.velcdn.com/images/juntae_94/post/c8f6d36d-c9c7-4a7f-88c4-c6b5c33860e3/image.png" alt=""></li>
</ul>
<h3 id="파이프-라인-작성">파이프 라인 작성</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/a4b76ed0-ace8-4718-8423-e9188fb4045c/image.png" alt=""></p>
<h3 id="빌드-성공">빌드 성공</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/1e813e13-b923-4e1f-99b6-77fec760c0c6/image.png" alt=""></p>
<h2 id="github-webhooks-설정">Github Webhooks 설정</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/26b09872-0326-406f-9116-dbc3d4f7f54f/image.png" alt=""></p>
<h2 id="젠킨스-트리거-설정">젠킨스 트리거 설정</h2>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/53573a2f-def6-4c9c-8006-712957872eca/image.png" alt=""></p>
<h2 id="자동배포-성공">자동배포 성공</h2>
<h3 id="git-push-트리거-생성">Git push 트리거 생성</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/e9e56a73-3e8b-4b45-bd39-1ad5f97bdfbe/image.png" alt=""></p>
<h3 id="젠킨스-자동-빌드-실행">젠킨스 자동 빌드 실행</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/26c327f3-a97b-40f3-8bcc-d7d149ab6a54/image.png" alt=""></p>
<h2 id="☠️-배포-작업중-막혔던-내용">☠️ 배포 작업중 막혔던 내용</h2>
<h3 id="🤯-openjdk-17-jdk">🤯 openjdk-17-jdk</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/65ee513b-3608-4543-9dfe-fd9711200b1d/image.png" alt=""></p>
<ul>
<li><code>JDK</code>를 <code>Doker</code>에서는 설치를 해줘서 왜 안되지 하면서 계속 <code>JDK</code> 삭제하고 다시 설치하고, 또 환경변수 설정이 잘못됐나 확인하며 시간을 많이 보냈다. </li>
</ul>
<h3 id="😏-해결-방법">😏 해결 방법</h3>
<ul>
<li>젠킨스에서 JDK를 사용하기 위해서는 설정을 해줘야 한다.<blockquote>
<ol>
<li>젠킨스 관리 페이지에 로그인합니다.</li>
<li>좌측 메뉴에서 <code>&quot;시스템 설정&quot;</code>을 선택합니다.</li>
<li>JDK 섹션으로 스크롤하거나 <code>&quot;JDK installations...&quot;</code> 링크를 클릭합니다.</li>
<li><code>&quot;Add JDK&quot;</code> 버튼을 클릭하여 새로운 JDK 설정을 추가합니다.</li>
<li>JDK 설정 페이지에서 다음 정보를 입력합니다:</li>
<li>&quot;Name&quot;: JDK의 이름을 지정합니다. (예: JDK 11)</li>
<li>&quot;JAVA_HOME&quot;: JDK의 설치 경로를 입력합니다.</li>
<li>저장을 클릭하여 JDK 설정을 저장합니다</li>
</ol>
</blockquote>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/19fba06f-7ff7-40e4-b635-99024ae1ae06/image.png" alt=""></p>
<hr>
<h3 id="🤯-docker-rm-fail">🤯 Docker Rm Fail</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/9c2b371d-e59a-4583-9461-cef4a2174688/image.png" alt=""></p>
<ul>
<li>처음 빌드 할경우 <code>Docker Rm</code>은 정상 작동한다. 하지만 이후 <code>Build Docker Images</code> 에서 실패를 할경우 다시 재빌드를 하게 되면 이전에 <code>Docker Rm</code>에서 이미 이미지와 컨테이너가 삭제 되었기 때문에 삭제할게 없어서 에러가 발생한다.</li>
</ul>
<h3 id="😏-해결방안">😏 해결방안</h3>
<ul>
<li>수동으로 도커이미지와 도커컨테이너를 만들어주고 빌드를 돌린다.</li>
<li>파이프라인에서 도커이미지, 도커컨테이너가 있으면 삭제하고 없으면 넘어간다 라는 파이프라인 코드를 작성해 준다. (추후 도전예정)</li>
</ul>
<hr>
<h3 id="🤯-build-docker-image">🤯 Build Docker image</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/d57e8b40-64a6-45d5-b7e3-70272c0fcdc6/image.png" alt=""></p>
<ul>
<li>도커 이미지 빌드에서 오류가 났다. 분명 리눅스 환경에서는 명령어가 잘 수행하지만 빌드에서는 실패를 했다. 원인을 찾다보니 <code>Dockerfile</code>을 찾을수 없다고 한다. 하지만 분명 리눅스 환경에서 도커파일을 설치했는데 의문이 들었다. 그래서 도커파일을 못찾는 줄 알고 경로를 설정하거나 절대경로를 설정해도 원인을 찾을수 없었다.</li>
</ul>
<h3 id="😏-해결방안-1">😏 해결방안</h3>
<ul>
<li>깃 레포지터리에 <code>Dockerfile</code>을 따로 만들어 주어야 한다. 리눅스환경에 도커파일이 있으면 될줄 알았지만 아니였다. 파이프라인은 <code>도커 -&gt; 젠킨스 컨테이너 -&gt; 젠킨스내부의 도커</code> 에서 실행되기 떄문이다.</li>
</ul>
<hr>
<h3 id="🤯-githook">🤯 Githook</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/1051fca4-96bd-4699-ad97-635a3dca60bc/image.png" alt=""></p>
<ul>
<li><code>Payload URL</code> 정보가 잘못됐다고 한다. 원인을 몰라서 <code>http</code> -&gt; <code>https</code>도 바꿔보고 포트를 <code>8080</code>으로 바꿔보고 해봐도 되지않았다.</li>
</ul>
<h3 id="😏-해결방안-2">😏 해결방안</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/cd58db05-bb9a-4fb2-ae3a-b99c91ce8640/image.png" alt=""></p>
<ul>
<li>수정예정</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Http, Https, 대칭키 , 비대칭키]]></title>
            <link>https://velog.io/@juntae_94/Http-Https-%EB%8C%80%EC%B9%AD%ED%82%A4-%EB%B9%84%EB%8C%80%EC%B9%AD%ED%82%A4</link>
            <guid>https://velog.io/@juntae_94/Http-Https-%EB%8C%80%EC%B9%AD%ED%82%A4-%EB%B9%84%EB%8C%80%EC%B9%AD%ED%82%A4</guid>
            <pubDate>Tue, 09 May 2023 13:37:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://static.semrush.com/blog/uploads/media/92/4e/924e69f58259f96645a57d5bf4450017/EN-HTTP-HTTPS.webp" alt=""></p>
<h1 id="httphypertext-transfer-protocol">HTTP(Hypertext Transfer Protocol)</h1>
<ul>
<li>인터넷에서 웹 페이지를 전송하는 데 사용되며, 데이터 전송 시에 보안 기능이 없다.</li>
<li>HTTP는 암호화되지 않기 때문에 누구나 데이터를 볼 수 있다.</li>
<li>개인 정보를 전송하는 경우 보안에 취약</li>
</ul>
<h1 id="httpshypertext-transfer-protocol-secure">HTTPS(Hypertext Transfer Protocol Secure)</h1>
<ul>
<li>HTTPS는 <code>SSL(Secure Sockets Layer)</code> 또는 <code>TLS(Transport Layer Security)</code> 프로토콜을 사용하여 데이터를 암호화하고 보호</li>
<li>제 3자가 볼 수 없다. 개인 정보를 전송하는데 안전함</li>
<li>기관으로부터 검증된 사이트만 주소에 https 사용이 허가해줌<ul>
<li>접속하는 사이트가 믿을만한 사이트인지 알려준다.</li>
</ul>
</li>
</ul>
<p><img src="https://cheapsslweb.com/blog/wp-content/uploads/2022/10/symmetric-encryption-vs-asymmetric-encryption.jpg" alt=""></p>
<h1 id="🔑-대칭키symmetric-key">🔑 대칭키(Symmetric Key)</h1>
<ul>
<li><code>하나의 비밀 키(secret key)</code>를 사용하여 암호화와 복호화를 수행하는 암호화 방식</li>
<li>빠르고 간단한 구현이 가능하기 때문에 대용량 데이터를 암호화하는 데 유용</li>
</ul>
<h1 id="🔑-비대칭키asymmetric-key">🔑 비대칭키(Asymmetric Key)</h1>
<ul>
<li><code>공개 키(public key)</code>와 <code>비밀 키(secret key)</code> <strong>두 개의 키</strong>를 사용하여 암호화와 복호화를 수행하는 암호화 방식</li>
<li>대칭키보다 더 안전하며, 공개 키는 유출시 문제가 없다.</li>
<li>인터넷에서 정보를 안전하게 교환하는 데 널리 사용</li>
</ul>
<h3 id="📎-참고영상">📎 참고영상</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=H6lpFRpyl14&amp;ab_channel=%EC%96%84%ED%8C%8D%ED%95%9C%EC%BD%94%EB%94%A9%EC%82%AC%EC%A0%84">HTTPS가 뭐고 왜 쓰나요? (Feat. 대칭키 vs. 비대칭키)
</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[로깅]]></title>
            <link>https://velog.io/@juntae_94/%EB%A1%9C%EA%B9%85</link>
            <guid>https://velog.io/@juntae_94/%EB%A1%9C%EA%B9%85</guid>
            <pubDate>Thu, 27 Apr 2023 02:51:40 GMT</pubDate>
            <description><![CDATA[<h1 id="🥸-로깅logging">🥸 로깅(Logging)</h1>
<ul>
<li>프로그램 동작시 발생하는 모든일을 기록하는 행위</li>
<li>기록 자체를 로그(log)라고 함</li>
<li>출력형식을 지정할 수 있음</li>
<li>로깅 시스템은 메시지 레벨에 따라 출력될 메시지를 필터링하고 지정가능</li>
<li>콘솔뿐아니라 파일, 네트워크에도 로그를 별도에 위치에 남길 수 있음</li>
<li>디버깅을 사용하기 어려운 환경에서의 최선의 선택</li>
</ul>
<h2 id="💡-로그레벨">💡 로그레벨</h2>
<ul>
<li>로그에 남겨지는 메시지의 중요도를 나타내는 수준<blockquote>
<p>개발자가 의도한 에러</p>
<ul>
<li><code>TRACE</code> : 가장 상세한 로그 레벨, 개발환경에서 버그를 해결하기 위해 사용 </li>
<li><code>DEBUG</code> : 개발 단계에서 프로그램의 실행 과정을 추적하기 위해 사용, 일반적으로 코드 흐름과 변수의 값을 추적</li>
<li><code>INFO</code> : 명확한 의도가 있는 에러, 요구사항에 따라 시스템 동작을 보여줄때 사용</li>
<li><code>WARN</code> : 에러가 될 수 있는 잠재적 가능성이 있는 경우 (ex : 데이터베이스 연결이 실패하거나, 파일을 찾을 수 없는 경우)</li>
</ul>
<hr>
<p>개발자가 의도하지 않은 에러</p>
<ul>
<li><code>ERROR</code> : 로그는 반드시 처리, 의도하지 않은 에러가 발생하는 경우 (프로그램 종료 X)</li>
<li><code>FATAL</code> : 애플리케이션이 실행 중지될 수 있는 치명적인 오류</li>
</ul>
</blockquote>
</li>
</ul>
<h2 id="🔎-디버깅">🔎 디버깅</h2>
<ul>
<li>예외사항을 가장 잘 파악할 수 있음 (변수의 값이나, 메모리 주소등을 <code>breakPoint</code> 를 활용해 확인가능)</li>
<li>소프트웨어 버그(Bug)를 찾아내고 수정하는 과정</li>
<li>스택 트레이스(Stack Trace)나 콘솔 출력 등의 디버깅 정보를 활용하여 버그를 추적하고 해결</li>
</ul>
<h3 id="systemoutprintln">System.out.println()</h3>
<ul>
<li>간단한 디버깅용으로 사용되는 콘솔 출력 메소드</li>
<li>프로그램에서 로그 메시지를 수집하거나 분석하는 데 사용 X</li>
</ul>
<h2 id="🔎-slf4jsimple-logging-facade-for-java">🔎 SLF4J(Simple Logging Facade for Java)</h2>
<p><img src="https://www.notion.so/image/https%3A%2F%2Fuser-images.githubusercontent.com%2F48986787%2F125076883-6b819680-e0fb-11eb-96fb-c1a344bc45d0.png?id=d2ceb84e-fd11-4a0f-805c-36fe96b95e22&table=block&spaceId=c69962b0-3951-485b-b10a-5bb29576bba8&width=2000&userId=e3efc8b1-cba5-4e0a-8309-0233bb686e17&cache=v2" alt=""></p>
<ul>
<li>로깅 프레임워크</li>
<li>자바 어플리케이션에서 로깅에 대한 <code>추상화</code> 계층을 제공하는 인터페이스를 제공 (단독으로 사용 X)</li>
</ul>
<h3 id="slf4j-모듈">SLF4J 모듈</h3>
<blockquote>
<ul>
<li>Bridge : 다른 로깅 <code>API</code>로부터 <code>SLF4J API</code>로 연결해주는 도구, <code>Binding</code>과 같은 프레임워크를 사용 X</li>
<li>API : 로깅에 대한 추상 레이어(인터페이스) 제공, 하나의 API모듈에 하나의 Binding을 둬야한다.</li>
<li>Binding : API를 로깅구현체와 연결하는 도구</li>
</ul>
</blockquote>
<h3 id="📎-참고-자료">📎 참고 자료</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=1MD5xbwznlI&amp;t=402s&amp;ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC">[10분 테코톡] ☂️ 검프의 Logging(로깅) #1</a></li>
<li><a href="https://www.youtube.com/watch?v=JqZzy7RyudI&amp;t=127s&amp;ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC">[10분 테코톡] ☂️ 검프의 Logging(로깅) #2
</a></li>
<li><a href="https://www.youtube.com/watch?v=MxxeKXydn4A&amp;ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC">[10분 테코톡] 🥂무늬의 로깅
</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[개인 코.테 메모장]]></title>
            <link>https://velog.io/@juntae_94/%EA%B0%9C%EC%9D%B8-%EC%BD%94.%ED%85%8C-%EB%A9%94%EB%AA%A8%EC%9E%A5</link>
            <guid>https://velog.io/@juntae_94/%EA%B0%9C%EC%9D%B8-%EC%BD%94.%ED%85%8C-%EB%A9%94%EB%AA%A8%EC%9E%A5</guid>
            <pubDate>Wed, 19 Apr 2023 00:40:07 GMT</pubDate>
            <description><![CDATA[<h1 id="array-">Array []</h1>
<h2 id="int---list">int[] -&gt; List</h2>
<pre><code class="language-java">List&lt;Integer&gt; intList = Arrays.stream(arr)
                              .boxed() // int -&gt; Integer
                              .collect(Collectors.toList());</code></pre>
<h2 id="오름차순-정렬">오름차순 정렬</h2>
<pre><code class="language-java">int[] sortedArr = Arrays.stream(arr)
                        .sorted()
                        .toArray();</code></pre>
<h2 id="절대값-기준으로-정렬">절대값 기준으로 정렬</h2>
<pre><code class="language-java">int[] sortedArr = Arrays.stream(arr)
                        .boxed() // int -&gt; integer
                        .sorted(Comparator.comparingInt(Math::abs))
                        .mapToInt(Integer::intValue)
                        .toArray();</code></pre>
<h1 id="list">List&lt;&gt;</h1>
<h2 id="list---array">List -&gt; Array</h2>
<pre><code class="language-java">List&lt;Integer&gt; list = new ArrayList&lt;&gt;();
int[] array = list.stream().mapToInt(Integer::intValue).toArray();</code></pre>
<h1 id="hashmapkv">HashMap&lt;K,V&gt;</h1>
<h2 id="value-값으로-정렬하기">value 값으로 정렬하기</h2>
<pre><code class="language-java">Map&lt;Integer, Float&gt; map = new HashMap&lt;&gt;();

map.entrySet().stream()
//오름차순        .sorted(Map.Entry.comparingByValue())
//내림차순        .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
                .mapToInt(Map.Entry::getKey)
                .toArray();</code></pre>
<h2 id="값-넣기-값이-있으면--1-없으면-0">값 넣기 (값이 있으면 + 1, 없으면 0)</h2>
<pre><code class="language-java">HashMap&lt;Integer, Integer&gt; hashMap = new HashMap&lt;&gt;();
for (int arr : array) {
    hashMap.put(arr, hashMap.getOrDefault(arr, 0) + 1);
}</code></pre>
<h2 id="value-값으로-key값-구하기">Value 값으로 Key값 구하기</h2>
<pre><code class="language-java">for (Map.Entry&lt;Integer, Integer&gt; hash : hashMap.entrySet()) {
    if (hash.getValue() == maxValue) {
        answer.add(hash.getKey());
    }
}</code></pre>
<h1 id="set">Set&lt;&gt;</h1>
<h1 id="정규식">정규식</h1>
<h2 id="09-값인지">0~9 값인지</h2>
<pre><code class="language-java">String.matches(&quot;^[0-9]+$&quot;);

String.matches(&quot;\\d+&quot;);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[CORS(Cross-Origin Resource Sharing)]]></title>
            <link>https://velog.io/@juntae_94/CORSCross-Origin-Resource-Sharing</link>
            <guid>https://velog.io/@juntae_94/CORSCross-Origin-Resource-Sharing</guid>
            <pubDate>Wed, 12 Apr 2023 13:01:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://miro.medium.com/v2/resize:fit:1400/0*bI2yxKryqJzyUkud" alt=""></p>
<h1 id="📕-cors">📕 CORS</h1>
<ul>
<li>다른 출처간(웹사이트, API주소)의 리소스(주고 받는 데이터)를 추가 HTTP 헤더를 사용해 다른 출처의 리소스에 접근할 수 있는 권한을 부여하도록 <code>브라우저</code>에 알려주는 체제<h2 id="작동방식">작동방식</h2>
</li>
</ul>
<ol>
<li>요청에 Origin이라는 header(받는 쪽의 IP주소, 사용할 프로토콜...)를 추가 (scheme(요청할자원의 접근방법 http,ftp...), 도메인, 포트) 해서 API로 보낸다.</li>
<li>API서버는 답장 header에 지정된 ACAO 정보를 실어서 보낸다.</li>
<li>브라우저가 origin에서 보낸 출처값이 서버의 답장 헤더에 담긴 ACAO에 똑같이 있으면 리소스를 공유해준다.</li>
</ol>
<h3 id="출처origin이란-">출처(origin)이란 ?</h3>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/d8b154bb-cf59-4f15-9512-a90888d64486/image.png" alt=""></p>
<h2 id="📗-cors의-종류">📗 CORS의 종류</h2>
<h3 id="simple-request">Simple Request</h3>
<ul>
<li>브라우저에서 본 요청을 바로 보내며 서버에서는 추가적인 처리 없이 요청을 처리할 수 있습니다. </li>
</ul>
<h3 id="preflight-request">Preflight Request</h3>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*zCXcC1VkBB16BDXUxkWoew.png" alt=""></p>
<ul>
<li>본 요청을 보내기 전에 서버가 본 요청을 수락할 수 있는지 확인하기 위한 과정, 요청에 의해서 서버 정보가 바뀔 수 있기 때문에.</li>
<li>HTTP 메서드 중 OPTIONS 메서드를 사용하며, 브라우저는 이에 대한 응답으로 서버가 허용하는 메서드, 헤더, 출처 등에 대한 정보를 받아옵니다.<h2 id="sopsame-origin-policy">SOP(Same Origin Policy)</h2>
</li>
<li>SOP는 같은 출처에 속하는 리소스끼리는 자유롭게 상호작용할 수 있도록 허용하고, 다른 출처의 리소스에는 접근할 수 없도록 제한</li>
<li>XSS(Cross-Site Scripting) 공격과 CSRF(Cross-Site Request Forgery) 공격을 방지하는 데 중요한 역할</li>
</ul>
<h2 id="acaoaccess-control-allow-origin">ACAO(Access-Control-Allow-Origin)</h2>
<ul>
<li>CORS(Cross-Origin Resource Sharing)에서 서버에서 브라우저로 응답을 보낼 때 허용되는 출처(origin)를 설정하는 HTTP 헤더</li>
<li>서버에서 브라우저로 보내는 응답에 포함되며, 브라우저는 이를 통해 자신이 요청한 리소스가 허용된 출처에서 온 것인지 확인</li>
</ul>
<h3 id="📎-참고영상">📎 참고영상</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=bW31xiNB8Nc&amp;ab_channel=%EC%96%84%ED%8C%8D%ED%95%9C%EC%BD%94%EB%94%A9%EC%82%AC%EC%A0%84">웹개발 짜증유발자! CORS가 뭔가요?
</a></li>
<li><a href="https://www.youtube.com/watch?v=-2TgkKYmJt4&amp;t=47s&amp;ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC">[10분 테코톡] 🌳 나봄의 CORS</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[톰캣]]></title>
            <link>https://velog.io/@juntae_94/%ED%86%B0%EC%BA%A3</link>
            <guid>https://velog.io/@juntae_94/%ED%86%B0%EC%BA%A3</guid>
            <pubDate>Tue, 11 Apr 2023 14:24:47 GMT</pubDate>
            <description><![CDATA[<h1 id="😺-톰캣was">😺 톰캣(WAS)</h1>
<ul>
<li>Java Servlet, JavaServer Pages(JSP), Java Expression Language(EL)과 같은 Java 기술을 사용하여 동적인 웹 페이지를 생성하고,웹 어플리케이션을 실행</li>
<li>가볍고 빠르며, 모듈화된 아키텍처를 통해 필요한 기능만 선택하여 사용할 수 있습니다.</li>
<li>톰캣은 다양한 운영체제와 플랫폼에서 실행할 수 있다.</li>
</ul>
<h2 id="🤔-톰캣을-왜-사용할까-">🤔 톰캣을 왜 사용할까 ?</h2>
<ul>
<li>JSP 컴파일러 : 톰캣은 JSP 컴파일러인 Jasper를 내장하고 있어, JSP 페이지를 빠르고 효율적으로 실행할 수 있습니다.</li>
<li>서블릿 컨테이너 : 톰캣은 서블릿 컨테이너를 포함하고 있어, 웹 어플리케이션에서 서블릿을 실행하고 관리할 수 있습니다. 이를 통해, 동적인 웹 어플리케이션 개발이 용이해집니다.</li>
</ul>
<h3 id="서블릿">서블릿</h3>
<ul>
<li>자바 언어로 작성된 서버 사이드 웹 어플리케이션의 구성 요소 중 하나로, HTTP 요청에 대한 동적인 처리를 담당</li>
<li>서블릿은 HTTP 요청에 대한 처리를 위한 <code>doGet()</code>, <code>doPost()</code>, <code>doPut()</code> 등의 메소드를 제공하며, 필요한 경우에는 <code>init()</code>과 <code>destroy()</code> 등의 메소드를 오버라이딩하여 서블릿의 생명 주기를 관리할 수 있습니다.</li>
</ul>
<h3 id="서블릿-컨테이너">서블릿 컨테이너</h3>
<ul>
<li>클라이언트로부터 요청을 받아, 해당 요청을 처리하는 서블릿을 호출하고, 서블릿의 실행 결과를 클라이언트에게 반환합니다.<ul>
<li>서블릿의 생명 주기를 관리하고, HTTP 요청 및 응답 처리, 멀티 스레드 처리, 세션 관리, 보안 등 다양한 기능을 제공</li>
</ul>
</li>
<li>서블릿 컨테이너로는 Apache Tomcat, Jetty, JBoss 등이 있습니다.
<img src="https://velog.velcdn.com/images/juntae_94/post/a15096a9-8c46-4574-b5c6-62e4cddde430/image.png" alt=""></li>
</ul>
<h3 id="coyote">Coyote</h3>
<ul>
<li>Tomcat의 HTTP 커넥터(클라이언트와 서버 간에 HTTP 요청과 응답을 주고받는 역할) 구현체</li>
</ul>
<h3 id="catalina">Catalina</h3>
<ul>
<li>Tomcat의 서블릿 컨테이너 구현체</li>
<li>웹 어플리케이션의 시작과 종료, HTTP 요청 및 응답 처리, 세션 관리, JSP 컴파일 등을 수행</li>
</ul>
<h3 id="jasper">Jasper</h3>
<ul>
<li>Tomcat의 JSP(JavaServer Pages / HTML과 Java 코드를 혼합하여 동적인 웹 페이지를 생성하는 기술) 컴파일러</li>
<li>JSP 파일을 컴파일하여 서블릿 클래스로 변환하고, 그 결과를 서블릿 컨테이너(예: Tomcat의 Catalina)에 전달</li>
</ul>
<h3 id="📎-참고영상">📎 참고영상</h3>
<ul>
<li><a href="https://www.youtube.com/playlist?list=PLE0hRBClSk5Iqe64Gfj_ungnNcBhAQ3D_">Great-Stone - 톰캣 유튜브</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[IP주소,  포트포워딩, DMZ, DDNS]]></title>
            <link>https://velog.io/@juntae_94/IP%EC%A3%BC%EC%86%8C-%ED%8F%AC%ED%8A%B8%ED%8F%AC%EC%9B%8C%EB%94%A9-DMZ-DDNS</link>
            <guid>https://velog.io/@juntae_94/IP%EC%A3%BC%EC%86%8C-%ED%8F%AC%ED%8A%B8%ED%8F%AC%EC%9B%8C%EB%94%A9-DMZ-DDNS</guid>
            <pubDate>Tue, 11 Apr 2023 01:18:38 GMT</pubDate>
            <description><![CDATA[<h1 id="😈-ip-주소">😈 IP 주소</h1>
<h2 id="ipv4">IPv4</h2>
<ul>
<li>현재 인터넷에서 가장 널리 사용되는 IP 버전 중 하나</li>
<li>0~255사이의 숫자 4개로 이루어져 있다.</li>
<li>IPv4 주소의 수가 한정되어 있어서, 인터넷의 빠른 성장으로 인해 주소 고갈 문제가 발생 / 이를 해결하기위해 IPv6가 개발</li>
</ul>
<h2 id="ipv6">IPv6</h2>
<ul>
<li>IPv4의 주소 고갈 문제를 해결하고 더 많은 주소를 사용할 수 있도록 개발되었다.</li>
<li>128비트 이진수로 구성되어 있으며, 보통 8개의 16진수 블록으로 표시</li>
</ul>
<h2 id="포트포워딩port-forwarding">포트포워딩(port forwarding)</h2>
<ul>
<li>인터넷을 통해 연결된 장치에서 어떤 포트로 들어오는 데이터 패킷을 다른 장치로 전달하는 네트워크 설정 방법</li>
<li>수신 데이터가 NAT 방화벽을 우회하도록 하여 인터넷 연결 속도를 개선</li>
<li>내부 네트워크에 있는 특정 포트를 외부로 포워딩 (외부에서 내부 네트워크의 서비스에 접속가능)</li>
</ul>
<h2 id="dmz">DMZ</h2>
<ul>
<li>내부 네트워크와 외부 네트워크 사이에 위치한 별도의 지역</li>
<li>서버나 장비는 내부 네트워크와는 별도로 관리되며, 외부에서 접속 가능한 IP 주소를 사용</li>
</ul>
<h2 id="ddns">DDNS</h2>
<ul>
<li>동적 IP 주소를 가진 장치들을 쉽게 인터넷에 연결하기 위해 사용되는 기술</li>
<li>인터넷에 연결된 기기들이 쉽게 액세스되도록 하기 위한 서비스로, 인터넷에 연결된 기기들의 IP 주소를 고정 IP 주소로 변환하여 사용자가 쉽게 기기에 접속할 수 있도록 해준다.</li>
</ul>
<h3 id="📎-참고영상">📎 참고영상</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=GK3h936Co-k&amp;ab_channel=%EC%96%84%ED%8C%8D%ED%95%9C%EC%BD%94%EB%94%A9%EC%82%AC%EC%A0%84">IP주소를 알아봅시다! (Feat. 공인/사설/고정/유동IP, 포트포워딩, DMZ, DDNS)
</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링부트 - Port 8080 was already in use.]]></title>
            <link>https://velog.io/@juntae_94/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-Port-8080-was-already-in-use</link>
            <guid>https://velog.io/@juntae_94/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-Port-8080-was-already-in-use</guid>
            <pubDate>Fri, 31 Mar 2023 00:35:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/juntae_94/post/0f8be5f2-352f-4e6d-b66a-45f60ceea0f5/image.png" alt=""></p>
<p>이미 8080포트를 사용하고 있어서 사용을 못한다고 한다.
8080포트를 사용하는 PID 번호를 찾아준다.</p>
<pre><code class="language-bash">lsof -i :8080</code></pre>
<p><img src="https://velog.velcdn.com/images/juntae_94/post/7374582e-8c95-443e-ab7c-47bc88a86eb9/image.png" alt=""></p>
<p>저렇게 PID 번호가 나온다.
그럼 터미널을 열어서 8080를 사용하는 프로세스를 죽여준다.</p>
<pre><code class="language-bash">kill -9 PID번호</code></pre>
]]></description>
        </item>
    </channel>
</rss>