<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>  백엔드 개발자 라분(Laboon)의 블로그</title>
    <link>https://dev-dot.tistory.com/</link>
    <description>velog: https://velog.io/@jihwankim128
github: https://github.com/jihwankim128</description>
    <language>ko</language>
    <pubDate>Sun, 31 May 2026 05:41:58 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>  Laboon</managingEditor>
    <image>
      <title>  백엔드 개발자 라분(Laboon)의 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/6791461/attach/71eb9c0393194079ac96216e06373370</url>
      <link>https://dev-dot.tistory.com</link>
    </image>
    <item>
      <title>BOJ 17386 선분 교차 1, BOJ 17387 선분 교차 2</title>
      <link>https://dev-dot.tistory.com/entry/BOJ-17386-%EC%84%A0%EB%B6%84-%EA%B5%90%EC%B0%A8-1-BOJ-17387-%EC%84%A0%EB%B6%84-%EA%B5%90%EC%B0%A8-2</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제는 CCW를 통해 해결하는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CCW에 대한 자세한 포스트는 카테고리 - 알고리즘 종류에서 확인 가능하다.&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;CCW를 통해 어떻게 해결 할 수 있는지 확인해보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OgKnz/btsOWM7j7BF/Hcuar5E0haYBXCgL3XVlRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OgKnz/btsOWM7j7BF/Hcuar5E0haYBXCgL3XVlRk/img.png&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;618&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4984%; margin-right: 10px;&quot; data-widthpercent=&quot;50.08&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OgKnz/btsOWM7j7BF/Hcuar5E0haYBXCgL3XVlRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOgKnz%2FbtsOWM7j7BF%2FHcuar5E0haYBXCgL3XVlRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;818&quot; height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kyoxm/btsOY7CauPl/3t6zn6V73ujt6rzNwqpsw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kyoxm/btsOY7CauPl/3t6zn6V73ujt6rzNwqpsw1/img.png&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;620&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.3388%;&quot; data-widthpercent=&quot;49.92&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kyoxm/btsOY7CauPl/3t6zn6V73ujt6rzNwqpsw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fkyoxm%2FbtsOY7CauPl%2F3t6zn6V73ujt6rzNwqpsw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;818&quot; height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;선분이 교차하는 경우와 교차하지 않는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선분은 교차하는 경우와 교차하지 않는 경우로 가볍게 구분할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 방향을 따져보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sTEzr/btsOY6DgYSh/zrZ8vOupDmvjGzOJykPPWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sTEzr/btsOY6DgYSh/zrZ8vOupDmvjGzOJykPPWK/img.png&quot; data-origin-width=&quot;998&quot; data-origin-height=&quot;756&quot; data-is-animation=&quot;false&quot; width=&quot;362&quot; height=&quot;274&quot; data-widthpercent=&quot;49.97&quot; style=&quot;width: 49.385%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sTEzr/btsOY6DgYSh/zrZ8vOupDmvjGzOJykPPWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsTEzr%2FbtsOY6DgYSh%2FzrZ8vOupDmvjGzOJykPPWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;998&quot; height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qLevk/btsOZiKd7nM/gfuO2k9FqS7tIFhTcyvYkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qLevk/btsOZiKd7nM/gfuO2k9FqS7tIFhTcyvYkk/img.png&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;758&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4522%;&quot; data-widthpercent=&quot;50.03&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qLevk/btsOZiKd7nM/gfuO2k9FqS7tIFhTcyvYkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqLevk%2FbtsOZiKd7nM%2FgfuO2k9FqS7tIFhTcyvYkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1002&quot; height=&quot;758&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;교차하는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교차하는 경우 CCW(A,B,C)는 음수 CCW(A,B,D)는 양수를 갖게 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 CCW(C,D,A)는 양수, CCW(C,D,B)는 음수를 갖게 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 한 선분을 기준으로 다른 선분의 끝 점이 서로 다른 부호를 가지고 있으면 교차한다고 판단 할 수 있는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z5IOq/btsOXhTyjMG/nirBeuxCzkvGMT0cRPpiAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z5IOq/btsOXhTyjMG/nirBeuxCzkvGMT0cRPpiAK/img.png&quot; data-alt=&quot;교차하지 않는 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z5IOq/btsOXhTyjMG/nirBeuxCzkvGMT0cRPpiAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz5IOq%2FbtsOXhTyjMG%2FnirBeuxCzkvGMT0cRPpiAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;390&quot; height=&quot;295&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;교차하지 않는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 선분 AB만 예시로 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림과 같이 교차하지 않는 경우 CCW(A,B,C)와 CCW(A,B,D)는 무조건 같은 방향을 보게 될 것이다.&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;우리는 이제 CCW를 활용해 선분 교차 1 문제를 풀 수 있게 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1751289918632&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	static class Point {
		long x, y;

		Point(long x, long y) {
			this.x = x;
			this.y = y;
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		Point p1 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));
		Point p2 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));

		st = new StringTokenizer(br.readLine());
		Point p3 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));
		Point p4 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));

		if (isIntersect(p1, p2, p3, p4)) {
			System.out.println(1);
		} else {
			System.out.println(0);
		}
	}

	static boolean isIntersect(Point p1, Point p2, Point p3, Point p4) {
		long ccw1 = ccw(p1, p2, p3);
		long ccw2 = ccw(p1, p2, p4);
		long ccw3 = ccw(p3, p4, p1);
		long ccw4 = ccw(p3, p4, p2);
		if (((ccw1 &amp;gt; 0 &amp;amp;&amp;amp; ccw2 &amp;lt; 0) || (ccw1 &amp;lt; 0 &amp;amp;&amp;amp; ccw2 &amp;gt; 0)) &amp;amp;&amp;amp;
			((ccw3 &amp;gt; 0 &amp;amp;&amp;amp; ccw4 &amp;lt; 0) || (ccw3 &amp;lt; 0 &amp;amp;&amp;amp; ccw4 &amp;gt; 0)))
			return true;
		return false;
	}

	static long ccw(Point a, Point b, Point c) {
		return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
	}
}&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;해당 문제(17386)에서 입력 값은 100만으로 곱하기 연셈에서 충분하도록 long 자료형을 꼭 써주자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의해야 할 부분이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교차 판정을 편하게 하기 위해 ccw 간 곱셈을 사용하면 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ccw를 구하는 과정에서 100만 * 100만 이 발생할 것이고 그럼 부호 확인을 하는 과정에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ccw1 * ccw2 를 하면 (100만 * 100만) * (100만 * 100만)의 숫자 표현을 사용해야 하므로 오버 플로우가 발생 할 수 있다.&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;그럼 이렇게 17386을 해결했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 17387 선분 교차 2를 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;핵심은 &lt;b&gt;한 선분의 끝 점이 다른 선분이나 끝 점 위에 있는 것도 교차하는 것이다.&amp;nbsp;&lt;/b&gt;라는 내용이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;단순히 내용만 보면 ccw 결과가 0인 것으로 답을 구할 수 있을 것으로 예상된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;결과부터 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0gLw6/btsOYN43Gd9/QTrvdFlsOA8E7aevWdPv4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0gLw6/btsOYN43Gd9/QTrvdFlsOA8E7aevWdPv4K/img.png&quot; style=&quot;width: 32.7614%; margin-right: 10px;&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;416&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;33.54&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0gLw6/btsOYN43Gd9/QTrvdFlsOA8E7aevWdPv4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0gLw6%2FbtsOYN43Gd9%2FQTrvdFlsOA8E7aevWdPv4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;578&quot; height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ln5GD/btsOZCaCfMR/Xw3z3lxaK9wllOullKfGS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ln5GD/btsOZCaCfMR/Xw3z3lxaK9wllOullKfGS1/img.png&quot; style=&quot;width: 32.4213%; margin-right: 10px;&quot; data-origin-width=&quot;572&quot; data-origin-height=&quot;416&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;33.19&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ln5GD/btsOZCaCfMR/Xw3z3lxaK9wllOullKfGS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fln5GD%2FbtsOZCaCfMR%2FXw3z3lxaK9wllOullKfGS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbuDvS/btsOXgNO1PK/cY8UnCCIhNqkwEbSwGLGyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbuDvS/btsOXgNO1PK/cY8UnCCIhNqkwEbSwGLGyk/img.png&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;418&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.4918%;&quot; data-widthpercent=&quot;33.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbuDvS/btsOXgNO1PK/cY8UnCCIhNqkwEbSwGLGyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbuDvS%2FbtsOXgNO1PK%2FcY8UnCCIhNqkwEbSwGLGyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;576&quot; height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 CCW가 0이라는 것은 위처럼 3가지 케이스가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 그림만 봐도 알 수 있듯 이 중 3번째 케이스만 옳은 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 세 번째 그림 처럼 선분 AB 에서 CD가 끝에 걸쳤는지 확인하는 방법은 간단하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점C가 AB 내에 존재하는지 확인하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C의 X 좌표가 A와 B 좌표 내에 위치해야 함 -&amp;gt; &lt;b&gt;C.x &amp;gt;= min(A.x, B.x) &amp;amp;&amp;amp; C.x &amp;lt;= max(A.x, B.x)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C의 Y 좌표가 A와 B 좌표 내에 위치해야 함 -&amp;gt; &lt;b&gt;C.y &amp;gt;= min(A.y, B.y) &amp;amp;&amp;amp; C.y &amp;lt;= max(A.y, B.y) &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, ccw == 0 이고 ccw에서 점 C가 점 A와 B와 겹치면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1751291281698&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	static class Point {
		long x, y;

		Point(long x, long y) {
			this.x = x;
			this.y = y;
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		Point p1 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));
		Point p2 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));

		st = new StringTokenizer(br.readLine());
		Point p3 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));
		Point p4 = new Point(Long.parseLong(st.nextToken()), Long.parseLong(st.nextToken()));

		if (isIntersect(p1, p2, p3, p4)) {
			System.out.println(1);
		} else {
			System.out.println(0);
		}
	}

	static boolean isIntersect(Point p1, Point p2, Point p3, Point p4) {
		long ccw1 = ccw(p1, p2, p3);
		long ccw2 = ccw(p1, p2, p4);
		long ccw3 = ccw(p3, p4, p1);
		long ccw4 = ccw(p3, p4, p2);
		if (((ccw1 &amp;gt; 0 &amp;amp;&amp;amp; ccw2 &amp;lt; 0) || (ccw1 &amp;lt; 0 &amp;amp;&amp;amp; ccw2 &amp;gt; 0)) &amp;amp;&amp;amp;
			((ccw3 &amp;gt; 0 &amp;amp;&amp;amp; ccw4 &amp;lt; 0) || (ccw3 &amp;lt; 0 &amp;amp;&amp;amp; ccw4 &amp;gt; 0)))
			return true;

		if (ccw1 == 0L &amp;amp;&amp;amp; isOnSegment(p1, p2, p3)) return true;
		if (ccw2 == 0L &amp;amp;&amp;amp; isOnSegment(p1, p2, p4)) return true;
		if (ccw3 == 0L &amp;amp;&amp;amp; isOnSegment(p3, p4, p1)) return true;
		if (ccw4 == 0L &amp;amp;&amp;amp; isOnSegment(p3, p4, p2)) return true;
		return false;
	}

	static long ccw(Point a, Point b, Point c) {
		return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
	}

	static boolean isOnSegment(Point a, Point b, Point p) {
		return Math.min(a.x, b.x) &amp;lt;= p.x &amp;amp;&amp;amp; p.x &amp;lt;= Math.max(a.x, b.x) &amp;amp;&amp;amp;
			Math.min(a.y, b.y) &amp;lt;= p.y &amp;amp;&amp;amp; p.y &amp;lt;= Math.max(a.y, b.y);
	}
}&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;기존 1번 코드에서 isOnSegment 메서드로 일부 인지 확인하고 ccw == 0 인것을 통해 명확히 답을 구했다.&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>CCW</category>
      <category>기하학</category>
      <category>백준</category>
      <category>선분 교차</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/108</guid>
      <comments>https://dev-dot.tistory.com/entry/BOJ-17386-%EC%84%A0%EB%B6%84-%EA%B5%90%EC%B0%A8-1-BOJ-17387-%EC%84%A0%EB%B6%84-%EA%B5%90%EC%B0%A8-2#entry108comment</comments>
      <pubDate>Mon, 30 Jun 2025 22:49:15 +0900</pubDate>
    </item>
    <item>
      <title>CCW (Counter Clock Wise)</title>
      <link>https://dev-dot.tistory.com/entry/CCW-Counter-Clock-Wise</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;세 점의 방향성을 판단하는 기하학적 문제&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8YTQX/btsOZuDPADm/PcbZjDeGYLBgdHdZWbatT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8YTQX/btsOZuDPADm/PcbZjDeGYLBgdHdZWbatT0/img.png&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;992&quot; data-is-animation=&quot;false&quot; width=&quot;343&quot; height=&quot;344&quot; style=&quot;width: 32.5143%; margin-right: 10px;&quot; data-widthpercent=&quot;33.29&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8YTQX/btsOZuDPADm/PcbZjDeGYLBgdHdZWbatT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8YTQX%2FbtsOZuDPADm%2FPcbZjDeGYLBgdHdZWbatT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;990&quot; height=&quot;992&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qQokA/btsOZjPSVc6/keCm7dU5c2MQ9ydpURkbg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qQokA/btsOZjPSVc6/keCm7dU5c2MQ9ydpURkbg1/img.png&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;980&quot; data-is-animation=&quot;false&quot; width=&quot;303&quot; height=&quot;303&quot; style=&quot;width: 32.58%; margin-right: 10px;&quot; data-widthpercent=&quot;33.36&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qQokA/btsOZjPSVc6/keCm7dU5c2MQ9ydpURkbg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqQokA%2FbtsOZjPSVc6%2FkeCm7dU5c2MQ9ydpURkbg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;980&quot; height=&quot;980&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3Uiw2/btsOYSyGjpS/7wxkMSqrV69PJ0qn1L8bi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3Uiw2/btsOYSyGjpS/7wxkMSqrV69PJ0qn1L8bi0/img.png&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;974&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.58%;&quot; data-widthpercent=&quot;33.35&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3Uiw2/btsOYSyGjpS/7wxkMSqrV69PJ0qn1L8bi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3Uiw2%2FbtsOYSyGjpS%2F7wxkMSqrV69PJ0qn1L8bi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;974&quot; height=&quot;974&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;반시계 방향 시계 방향  일직선&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CCW 값에 의해 세 점이 어느 방향으로 향하는지 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CCW(A, B, C) = (B.x - A.x) &amp;times; (C.y - A.y) - (B.y - A.y) &amp;times; (C.x - A.x)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 값에 따라 양수: 반시계방향, 음수: 시계 방향, 0: 일직선을 나타낸다.&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;CCW가 어떻게 도출되는지 알아보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Tlvw/btsOZyTBCzQ/afK4om96KVjNcHcWEEWZYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Tlvw/btsOZyTBCzQ/afK4om96KVjNcHcWEEWZYk/img.png&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;368&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.0674%; margin-right: 10px;&quot; data-widthpercent=&quot;48.63&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Tlvw/btsOZyTBCzQ/afK4om96KVjNcHcWEEWZYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Tlvw%2FbtsOZyTBCzQ%2FafK4om96KVjNcHcWEEWZYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;368&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LKbor/btsOY6QOwdV/0kshbOwKTtevIgJ5xU8FEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LKbor/btsOY6QOwdV/0kshbOwKTtevIgJ5xU8FEK/img.png&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;386&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.7698%;&quot; data-widthpercent=&quot;51.37&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LKbor/btsOY6QOwdV/0kshbOwKTtevIgJ5xU8FEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLKbor%2FbtsOY6QOwdV%2F0kshbOwKTtevIgJ5xU8FEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;좌표 원점&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌측 그림과 같은 좌표를 가진 세 점이 있을 때, A를 원점으로 C와 B의 벡터를 구하면 오른쪽 그림과 같이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fff3cd; color: #333333; text-align: start;&quot;&gt;A' = (0, 0) &amp;larr; A에서 A를 뺀 것&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fff3cd; color: #333333; text-align: start;&quot;&gt;B' = (bx - ax, by - ay) &amp;larr; B에서 A를 뺀 것 (6, 2) 이라고 가정&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fff3cd; color: #333333; text-align: start;&quot;&gt;C' = (cx - ax, cy - ay) &amp;larr; C에서 A를 뺀 것 (7, 3) 라고 가정&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 두 벡터간의 회전 방향을 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2D에서 외적 공식:&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fff3cd; color: #333333; text-align: start;&quot;&gt;벡터 u = (ux, uy)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fff3cd; color: #333333; text-align: start;&quot;&gt;벡터 v = (vx, vy)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fff3cd; color: #333333; text-align: start;&quot;&gt;u &amp;times; v = ux &amp;times; vy - uy &amp;times; vx&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;2차원 벡터의 외적 공식을 통해 방향을 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B`(6, 2)와 C`(7, 3)의 방향을 구해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6 * 3 - 2 * 7 = 4로 양수인 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bE2gQq/btsOZiwGV7I/7ZLyLhEWa2Gmp4HLL07KCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bE2gQq/btsOZiwGV7I/7ZLyLhEWa2Gmp4HLL07KCK/img.png&quot; data-alt=&quot;반시계 방향으로 향함&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bE2gQq/btsOZiwGV7I/7ZLyLhEWa2Gmp4HLL07KCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbE2gQq%2FbtsOZiwGV7I%2F7ZLyLhEWa2Gmp4HLL07KCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;304&quot; height=&quot;712&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;712&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;반시계 방향으로 향함&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 그림에서 확인한 결과도 B -&amp;gt; C 를 향하는 방향은 반시계방향이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원점 이동부터 2차원 외적 공식을 모두 적용한게 CCW 이다.&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;우리는 앞으로 CCW를 활용해 문제를 해결 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 대표적으로 BOJ의 선분 교차 1 문제를 해결해보자. (다음 포스트에서)&lt;/p&gt;</description>
      <category>알고리즘/알고리즘 종류</category>
      <category>CCW</category>
      <category>기하학</category>
      <category>백준</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/107</guid>
      <comments>https://dev-dot.tistory.com/entry/CCW-Counter-Clock-Wise#entry107comment</comments>
      <pubDate>Mon, 30 Jun 2025 22:14:15 +0900</pubDate>
    </item>
    <item>
      <title>BOJ 1106 호텔</title>
      <link>https://dev-dot.tistory.com/entry/BOJ-1106-%ED%98%B8%ED%85%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1106&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1106&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유명한 배낭 문제이다.&lt;/p&gt;
&lt;pre id=&quot;code_1751117109304&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	static class Info {
		int cost;
		int additionalCustomers;

		public Info(int cost, int additionalCustomers) {
			this.cost = cost;
			this.additionalCustomers = additionalCustomers;
		}
	}

	static Info[] infos = new Info[21];

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int c = Integer.parseInt(st.nextToken());
		int n = Integer.parseInt(st.nextToken());
		for (int i = 0; i &amp;lt; n; i++) {
			st = new StringTokenizer(br.readLine());
			int cost = Integer.parseInt(st.nextToken());
			int additionalCustomers = Integer.parseInt(st.nextToken());
			infos[i] = new Info(cost, additionalCustomers);
		}

		int maxCustomers = c + 100;
		int[] dp = new int[maxCustomers + 1];
		Arrays.fill(dp, Integer.MAX_VALUE);
		dp[0] = 0;

		for (int i = 0; i &amp;lt; n; i++) {
			int cost = infos[i].cost;
			int customers = infos[i].additionalCustomers;

			for (int j = customers; j &amp;lt;= maxCustomers; j++) {
				if (dp[j - customers] != Integer.MAX_VALUE) {
					dp[j] = Math.min(dp[j], dp[j - customers] + cost);
				}
			}
		}

		int answer = Integer.MAX_VALUE;
		for (int i = c; i &amp;lt;= maxCustomers; i++) {
			answer = Math.min(answer, dp[i]);
		}

		System.out.println(answer);
	}
}
/*
 * PM 09:52 ~
 * 홍보 도시 -&amp;gt; 홍보 비용, 증가 고객 정보
 * 호텔의 고객을 적어도 C명 늘리기 위한 최소 투자 비용
 *  */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/456195195&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/biV7Ex/hyZfqxiknN/1Y78WBlTVZdYSttqBw0txk/img.jpg?width=1320&amp;amp;height=936&amp;amp;face=0_0_1320_936,https://scrap.kakaocdn.net/dn/cfpGMu/hyZfvFnn1x/k4p6jHgTJkKLC0TiKDxVL1/img.jpg?width=1320&amp;amp;height=936&amp;amp;face=0_0_1320_936&quot; data-video-width=&quot;860&quot; data-video-height=&quot;610&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;610&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;'  백엔드 개발자 라분(Laboon)의 블로그'에서 업로드한 동영상&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/456195195?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;610&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;</description>
      <category>알고리즘/백준</category>
      <category>냅색</category>
      <category>배낭</category>
      <category>백준</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/106</guid>
      <comments>https://dev-dot.tistory.com/entry/BOJ-1106-%ED%98%B8%ED%85%94#entry106comment</comments>
      <pubDate>Sat, 28 Jun 2025 22:30:09 +0900</pubDate>
    </item>
    <item>
      <title>Unbounded Knapsack (무한 배낭)</title>
      <link>https://dev-dot.tistory.com/entry/Unbounded-Knapsack-%EB%AC%B4%ED%95%9C-%EB%B0%B0%EB%82%AD</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;중요 키워드:&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;각 물건을 &lt;b&gt;무한개&lt;/b&gt; 선택 가능&quot;&lt;/li&gt;
&lt;li&gt;&quot;같은 물건을 여러 번 사용&quot;&lt;/li&gt;
&lt;li&gt;&quot;동전 교환&quot;, &quot;최소 개수&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시간 복잡도: O(nW)&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 아이디어:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[w] = 무게 w에서 최대 가치 (같은 물건 재사용 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1751116873495&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UnboundedKnapsack {
    // 최대 가치 구하기
    public static int maxValue(int W, int[] weights, int[] values) {
        int[] dp = new int[W + 1];
        
        for (int i = 0; i &amp;lt; weights.length; i++) {
            // 앞에서부터 순회 (중복 사용 허용)
            for (int w = weights[i]; w &amp;lt;= W; w++) {
                dp[w] = Math.max(dp[w], dp[w - weights[i]] + values[i]);
            }
        }
        return dp[W];
    }
    
    // 최소 개수 구하기 (동전 교환 문제)
    public static int minCount(int target, int[] coins) {
        int[] dp = new int[target + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        
        for (int coin : coins) {
            for (int i = coin; i &amp;lt;= target; i++) {
                if (dp[i - coin] != Integer.MAX_VALUE) {
                    dp[i] = Math.min(dp[i], dp[i - coin] + 1);
                }
            }
        }
        return dp[target] == Integer.MAX_VALUE ? -1 : dp[target];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/알고리즘 종류</category>
      <category>knapsack</category>
      <category>무한 배낭</category>
      <category>배낭</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/105</guid>
      <comments>https://dev-dot.tistory.com/entry/Unbounded-Knapsack-%EB%AC%B4%ED%95%9C-%EB%B0%B0%EB%82%AD#entry105comment</comments>
      <pubDate>Sat, 28 Jun 2025 22:24:03 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ 9252] LCS2</title>
      <link>https://dev-dot.tistory.com/entry/BOJ-9252-LCS2</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LCS(Longest Common Subsequence, 최장 공통 부분 수열) 문제&lt;br /&gt;두 수열이 주어진다.&lt;br /&gt;부분 수열을 찾는다.&lt;br /&gt;그 중 가장 긴 것을 찾는다.&lt;br /&gt;예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.&lt;br /&gt;LCS의 길이와 LCS를 출력한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제한 사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0.1s, java11: 0.4s&lt;br /&gt;각 수열 = 최대 1000글자&lt;br /&gt;LCS가 0인 경우, 길이만 출력&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 포인트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LCS를 naive하게 찾아보자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A 수열과 B 수열이 있을 때, B 수열로 A 수열의 LCS를 찾는다면 O(N^3)이 발생한다.&lt;/li&gt;
&lt;li&gt;B 수열의 각 글자를 첫 부분 수열의 글자로 생각하고 찾는다면 1000 글자에 대해 각 각 1000 - i 글자 수를 연산해야 된다. (N^2)&lt;/li&gt;
&lt;li&gt;각 N^2의 부분 수열의 글자가 A 수열에 있는지 확인해야한다. (N^3)&lt;/li&gt;
&lt;li&gt;완전 탐색으로는 불가능 한 것을 알게 됐다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 또는 그리디, 이분 탐색과 같은 효율적인 알고리즘을 선택해야된다.&lt;br /&gt;해당 문제는 유명한 LCS 문제라서 DP인 것은 자명하다.&lt;br /&gt;하지만, 처음 문제를 봤을 때 DP인지 어떻게 알 수 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 포인트가 3가지 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;부분 수열 -&amp;gt; B 수열 중 앞 부분의 작은 수열에 다음 글자를 추가한다면 메모제이션을 활용할 수 있다.&lt;/li&gt;
&lt;li&gt;가장 긴 -&amp;gt; 최장을 찾는 문제에서는 DP를 의심할 수 있다.&lt;/li&gt;
&lt;li&gt;시간 제한 -&amp;gt; 채 1초도 안되는 짧은 시간은 선형 탐색이나 상수 탐색에서 주로 나온다. DP를 의심할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 로직&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eopn7z/btsNdVDyr5w/YJt9xKhZMSiNYhTOyOt4KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eopn7z/btsNdVDyr5w/YJt9xKhZMSiNYhTOyOt4KK/img.png&quot; data-alt=&quot;ACAYKP vs CAPCAK DP Table&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eopn7z/btsNdVDyr5w/YJt9xKhZMSiNYhTOyOt4KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feopn7z%2FbtsNdVDyr5w%2FYJt9xKhZMSiNYhTOyOt4KK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;463&quot; height=&quot;448&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ACAYKP vs CAPCAK DP Table&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 테이블을 그려보면, 그림과 동일하다. ACAYKP 에서 바라보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A가 CAPCAK에서 A를 만난 순간부터 LCS는 1이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C는 이전에 A의 LCS가 있기 때문에, CAPCAK에서 C를 만나지 못한다면 부분 수열 A의 LCS가 AC의 LCS가 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, C를 만난다면 C를 만난 시점(바로 이전 부분 수열)까지의 LCS + 1 개이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 2가지 케이스만 존재하므로 점화식을 도출 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if ch1 == ch2 DP[i][j] = DP[i-1][j-1] + 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;else DP[i][j] = max(DP[i-1][j], DP[i][j-1])&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼, LCS의 문자를 뽑아내려면 어떻게 할 수 있을까? -&amp;gt; trace&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 수열의 길이부터 시작해서 dp 테이블을 통해 추적 할 수 있다.&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;if (A와 B의 길이가 각각 &amp;lt;= 0) return&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;else if (문자가 같다면) 문자 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;else DP 테이블에서 A, B를 통한 경로 중 더 큰 값으로 추적&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Main {

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static StringBuilder sb = new StringBuilder();
    static int[][] dp = new int[1001][1001];
    static String str1, str2;

    public static void main(String[] args) throws IOException {
        str1 = br.readLine();
        str2 = br.readLine();

        for (int i = 0; i &amp;lt; str1.length(); i++) {
            for (int j = 0; j &amp;lt; str2.length(); j++) {
                if (str1.charAt(i) == str2.charAt(j)) {
                    dp[i + 1][j + 1] = dp[i][j] + 1;
                } else {
                    dp[i+1][j+1] = Math.max(dp[i][j+1], dp[i+1][j]);
                }
            }
        }

        int maxLcsLength = dp[str1.length()][str2.length()];
        sb.append(maxLcsLength).append('\n');
        trace(str1.length(), str2.length());

        bw.write(sb.toString());
        bw.flush();
    }

    static void trace(int s1Idx, int s2Idx) {
        if (s1Idx &amp;lt;= 0 || s2Idx &amp;lt;= 0) {
            return;
        } else if (str1.charAt(s1Idx - 1) == str2.charAt(s2Idx - 1)) {
            trace(s1Idx - 1, s2Idx - 1);
            sb.append(str1.charAt(s1Idx - 1));
        } else if (dp[s1Idx - 1][s2Idx] &amp;gt;= dp[s1Idx][s2Idx - 1]) {
            trace(s1Idx - 1, s2Idx);
        } else {
            trace(s1Idx, s2Idx - 1);
        }
    }

}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/104</guid>
      <comments>https://dev-dot.tistory.com/entry/BOJ-9252-LCS2#entry104comment</comments>
      <pubDate>Tue, 8 Apr 2025 21:34:32 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ 17406] 배열 돌리기 4</title>
      <link>https://dev-dot.tistory.com/entry/BOJ-17406-%EB%B0%B0%EC%97%B4-%EB%8F%8C%EB%A6%AC%EA%B8%B0-4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문제 정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열의 최솟값을 구한다.&lt;/li&gt;
&lt;li&gt;배열의 최솟값은 각 행의 모든 원소의 합 중 가장 작은 값이다.&lt;/li&gt;
&lt;li&gt;배열이 주어지면 k번의 회전을 한다.&lt;/li&gt;
&lt;li&gt;각 회전은 r, c, s 값으로 회전한다.&lt;/li&gt;
&lt;li&gt;(r-s, c-s) 부터 (r+s, c+s) 까지 시계 방향으로 회전한다.&lt;/li&gt;
&lt;li&gt;회전 연산이 두 개 이상이면, 연산을 수행한 횟수에 따라 최종 배열이 달라진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제한 사항&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3 &amp;le; N, M &amp;le; 50&lt;/li&gt;
&lt;li&gt;1 &amp;le; K &amp;le; 6&lt;/li&gt;
&lt;li&gt;1 &amp;le; A[i][j] &amp;le; 100&lt;/li&gt;
&lt;li&gt;1 &amp;le; s&lt;/li&gt;
&lt;li&gt;1 &amp;le; r-s &amp;lt; r &amp;lt; r+s &amp;le; N&lt;/li&gt;
&lt;li&gt;1 &amp;le; c-s &amp;lt; c &amp;lt; c+s &amp;le; M&lt;/li&gt;
&lt;/ul&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;/li&gt;
&lt;li&gt;배열 회전의 최종 결과로 최종 배열을 획득 할 수 있으므로 가지치기 필요 없음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;배열 회전에 대한 구현력 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 로직&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백트래킹을 통해 다른 경우에 대한 회전 상태 저장하는 로직&lt;/li&gt;
&lt;li&gt;배열 시작 지점부터 종료 지점까지의 시계 방향 회전 로직&lt;/li&gt;
&lt;li&gt;최종 배열에서 최솟 값을 찾는 로직&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드&lt;/p&gt;
&lt;pre id=&quot;code_1743689552579&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.baekjoon.bruteforce_with_backtracking.boj17406;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

    static class Rotation {
        int r, c, s;
        public Rotation(int r, int c, int s) {
            this.r = r;
            this.c = c;
            this.s = s;
        }
    }
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int n, m, k;
    static int[][] arr = new int[51][51];
    static int[][] tempArr = new int[51][51];
    static boolean[] visited = new boolean[6];
    static Rotation[] rotationOrder = new Rotation[6];
    static int minValue = Integer.MAX_VALUE;

    public static void main(String[] args) throws IOException {
        Rotation[] rotations = input();
        backtrack(rotations, 0);
        System.out.println(minValue);
    }

    private static Rotation[] input() throws IOException {
        st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());

        for (int i = 1; i &amp;lt;= n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j &amp;lt;= m; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        Rotation[] rotations = new Rotation[k];
        for (int i = 0; i &amp;lt; k; i++) {
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            rotations[i] = new Rotation(r, c, s);
        }
        return rotations;
    }

    private static void backtrack(Rotation[] rotations, int depth) {
        if (depth == k) {
            for (int i = 1; i &amp;lt;= n; i++) tempArr[i] = Arrays.copyOf(arr[i], arr[i].length);
            for (int i = 0; i &amp;lt; k; i++) rotateArray(i);
            calculateArrayValue();
            return;
        }

        for (int i = 0; i &amp;lt; k; i++) {
            if (!visited[i]) {
                visited[i] = true;
                rotationOrder[depth] = rotations[i];
                backtrack(rotations, depth + 1);
                visited[i] = false;
            }
        }
    }

    private static void rotateArray(int idx) {
        int r = rotationOrder[idx].r;
        int c = rotationOrder[idx].c;
        int s = rotationOrder[idx].s;

        for (int layer = 1; layer &amp;lt;= s; layer++) {
            int sr = r - layer, sc = c - layer;
            int er = r + layer, ec = c + layer;

            int temp = tempArr[sr][sc];
            for (int i = sr; i &amp;lt; er; i++) tempArr[i][sc] = tempArr[i+1][sc];
            for (int j = sc; j &amp;lt; ec; j++) tempArr[er][j] = tempArr[er][j+1];
            for (int i = er; i &amp;gt; sr; i--) tempArr[i][ec] = tempArr[i-1][ec];
            for (int j = ec; j &amp;gt; sc; j--) tempArr[sr][j] = tempArr[sr][j-1];
            tempArr[sr][sc+1] = temp;
        }
    }

    private static void calculateArrayValue() {
        int minSum = Integer.MAX_VALUE;

        for (int i = 1; i &amp;lt;= n; i++) {
            int rowSum = 0;
            for (int j = 1; j &amp;lt;= m; j++) {
                rowSum += tempArr[i][j];
            }
            minSum = Math.min(minSum, rowSum);
        }

        minValue = Math.min(minValue, minSum);
    }

}&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;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1292&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDSIMs/btsM6JqZgwE/5VhCx1uDlBYrlIMgt1kUJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDSIMs/btsM6JqZgwE/5VhCx1uDlBYrlIMgt1kUJ0/img.png&quot; data-alt=&quot;그림1. 백트래킹 과정과 방문 처리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDSIMs/btsM6JqZgwE/5VhCx1uDlBYrlIMgt1kUJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDSIMs%2FbtsM6JqZgwE%2F5VhCx1uDlBYrlIMgt1kUJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;545&quot; height=&quot;328&quot; data-origin-width=&quot;1292&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림1. 백트래킹 과정과 방문 처리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가정: Rotattion가 3개가 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. r0, r1, r2 순서로 회전 연산 정보를 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 백트래킹 과정에서 r0, r2, r1 순서의 회전 연산 정보도 저장하게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cl2D2Z/btsM8ViT3Ca/GwyPZGLV88gKaz1kSDNzFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cl2D2Z/btsM8ViT3Ca/GwyPZGLV88gKaz1kSDNzFk/img.png&quot; data-alt=&quot;그림2. 배열 회전 연산&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cl2D2Z/btsM8ViT3Ca/GwyPZGLV88gKaz1kSDNzFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcl2D2Z%2FbtsM8ViT3Ca%2FGwyPZGLV88gKaz1kSDNzFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;542&quot; height=&quot;836&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림2. 배열 회전 연산&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 중심점으로 부터 s의 개수만큼 회전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. (r - 1, c - 1) to (r + 1, c + 1)까지 각 각 회전하는 구현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZaYhZ/btsM8M0QuCX/Wk7j6Er37wXvd06BOPlkB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZaYhZ/btsM8M0QuCX/Wk7j6Er37wXvd06BOPlkB0/img.png&quot; data-alt=&quot;3. 최종 연산&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZaYhZ/btsM8M0QuCX/Wk7j6Er37wXvd06BOPlkB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZaYhZ%2FbtsM8M0QuCX%2FWk7j6Er37wXvd06BOPlkB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;578&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3. 최종 연산&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 출처: &lt;a href=&quot;https://www.acmicpc.net/problem/17406&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/17406&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/103</guid>
      <comments>https://dev-dot.tistory.com/entry/BOJ-17406-%EB%B0%B0%EC%97%B4-%EB%8F%8C%EB%A6%AC%EA%B8%B0-4#entry103comment</comments>
      <pubDate>Thu, 3 Apr 2025 23:17:52 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ 1826] 연료 채우기</title>
      <link>https://dev-dot.tistory.com/entry/BOJ-1826-%EC%97%B0%EB%A3%8C-%EC%B1%84%EC%9A%B0%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;724&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GApEu/btsM1KvOPM4/sdmRHi8AFgk78H6YBzI8xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GApEu/btsM1KvOPM4/sdmRHi8AFgk78H6YBzI8xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GApEu/btsM1KvOPM4/sdmRHi8AFgk78H6YBzI8xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGApEu%2FbtsM1KvOPM4%2FsdmRHi8AFgk78H6YBzI8xk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;724&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;724&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;문제 정리&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;트럭으로 마을까지 이동 중 1KM를 이동 할 때마다 1L의 연료가 빠져 나가는 상황&lt;/li&gt;
&lt;li&gt;이동하는 곳곳에 N개의 주유소가 존재&lt;/li&gt;
&lt;li&gt;트럭은 충전 할 때 마다 연료를 충분히 충전할 수 있음.&lt;/li&gt;
&lt;li&gt;각 각의 주유소 위치와 연료의 양이 주어 질 때, 최소한으로 충전하는 횟수 구하기&lt;/li&gt;
&lt;li&gt;마을에 도착할 수 없는 경우 -1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;제한 사항 &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;제한사항 1: 주유소 개수 1 &amp;lt;= N &amp;lt;= 10,000&lt;/li&gt;
&lt;li&gt;제한사항 2: 주유소 위치 1 &amp;lt;= a &amp;lt;= 1,000,000&lt;/li&gt;
&lt;li&gt;제한사항 3: 주유소 연료 1 &amp;lt;= b &amp;lt;= 100&lt;/li&gt;
&lt;li&gt;제한사항 4: 현재 위치에서 마을까지 거리 1 &amp;lt;= L &amp;lt;= 1,000,000&lt;/li&gt;
&lt;li&gt;제한사항 5: 현재 트럭의 연료량 1 &amp;lt;= P &amp;lt;= 1,000,000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;핵심 키포인트&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;충분히 많이 충전 -&amp;gt; 한 번에 최대한 많은 이익, 그리디의 핵심&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;핵심 포인트&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;거리와 연료 중 어느 것을 포커스로 두어야하는가?&lt;/li&gt;
&lt;li&gt;의심해야 할 포인트 1: 가장 많은 연료를 얻는 것이 좋은가?&lt;/li&gt;
&lt;li&gt;의심해야 할 포인트 2: 가장 멀리있는 것을 획득하는 것이 좋은가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;핵심 로직&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;한 번에 이동 할 수 있다면, 연료를 굳이 얻을 필요가 없다.&lt;/li&gt;
&lt;li&gt;현재까지 이동할 수 있는 거리(total oil)로 마을까지 이동할 수 있다면, 더 이상 연료가 필요없다.&lt;/li&gt;
&lt;li&gt;마을까지 이동할 수 없다면, 현재까지 이동할 수 있는 거리 중 최대의 오일을 선택한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;가정. 초기 연료 3, 목적지 10&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;초기 연료로 이동할 수 있는 위치는 3&lt;/li&gt;
&lt;li&gt;그 중 얻을 수 있는 최대 연료는 7&lt;/li&gt;
&lt;li&gt;더 많은 케이스를 생각해서 Heap을 통해 저장&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;힙을 꼭 사용해야하나요?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;매번 이동할 수 있는 거리 중 최대로 획득할 수 있는 연료를 선택하면 안되나요?&lt;/li&gt;
&lt;li&gt;추가로 이동할 수 있는 거리에서 획득하는 연료보다 이전까지 이동한 거리에서 획득하는 연료가 더 많은 연료를 제공할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.io.*;
import java.util.*;

public class Main {

    static class Position {
        int x;
        int oil;
        public Position(int x, int oil) {
            this.x = x;
            this.oil = oil;
        }
    }

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;

    public static void main(String[] args) throws IOException {
        int N = Integer.parseInt(br.readLine());

        Position[] gasStations = new Position[N];
        for (int i = 0; i &amp;lt; N; i++) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken());
            int oil = Integer.parseInt(st.nextToken());
            gasStations[i] = new Position(x, oil);
        }

        // 정렬되었다는 선 조건이 없으므로 거리 순으로 정렬
        Arrays.sort(gasStations, (a, b) -&amp;gt; a.x - b.x);

        st = new StringTokenizer(br.readLine());
        int destination = Integer.parseInt(st.nextToken());
        int currentOil = Integer.parseInt(st.nextToken());
        int currentPos = 0;
        int stationIndex = 0;
        int stopCount = 0;

        PriorityQueue&amp;lt;Integer&amp;gt; pq = new PriorityQueue&amp;lt;&amp;gt;((a, b) -&amp;gt; b - a);
        // 목적지에 도착할 때까지 반복
        while (currentPos + currentOil &amp;lt; destination) {
            // 이동 할 수 있는 거리 내 충전할 수 있는 oil을 모두 저장
            int canMovingDistance = currentPos + currentOil;
            while (stationIndex &amp;lt; N &amp;amp;&amp;amp; gasStations[stationIndex].x &amp;lt;= canMovingDistance) {
                pq.offer(gasStations[stationIndex].oil);
                stationIndex++;
            }

            // 충전할 수 있는 oil이 없다면, 이동할 수 없음.
            if (pq.isEmpty()) {
                stopCount = -1;
                break;
            }

            currentPos += pq.poll();
            stopCount++;
        }

        System.out.println(stopCount);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;문제 출처: &lt;a href=&quot;https://www.acmicpc.net/problem/1826&quot;&gt;https://www.acmicpc.net/problem/1826&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>그리디</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/102</guid>
      <comments>https://dev-dot.tistory.com/entry/BOJ-1826-%EC%97%B0%EB%A3%8C-%EC%B1%84%EC%9A%B0%EA%B8%B0#entry102comment</comments>
      <pubDate>Mon, 31 Mar 2025 01:07:49 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ 20207] 달력</title>
      <link>https://dev-dot.tistory.com/entry/BOJ-20207-%EB%8B%AC%EB%A0%A5</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eboq6T/btsM2KIPaDt/vspUVQC8r0OAWhKZBnQoYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eboq6T/btsM2KIPaDt/vspUVQC8r0OAWhKZBnQoYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eboq6T/btsM2KIPaDt/vspUVQC8r0OAWhKZBnQoYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feboq6T%2FbtsM2KIPaDt%2FvspUVQC8r0OAWhKZBnQoYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1084&quot; height=&quot;502&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;날짜가 1일 ~ 365일로 표시되어 있는 달력을 가지고 있음.&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 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;연속된 두 일자에 각 각 일정이 1개 이상있다면, 연속된 일정이다.&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;시작일이 가장 앞선 일정부터 차례대로 채워진다.&lt;/li&gt;
&lt;li&gt;시작일이 같은 경우 일정의 기간이 긴 것부터 채워진다.&lt;/li&gt;
&lt;li&gt;일정은 가능한 한 최 상단에 배치된다.&lt;/li&gt;
&lt;li&gt;일정 하나의 세로의 길이는 1이다.&lt;/li&gt;
&lt;li&gt;하루의 폭은 1이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제한사항&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일정의 개수 1 &amp;lt;= N &amp;lt;= 1,000&lt;/li&gt;
&lt;li&gt;시작 날짜 1 &amp;lt;= S &amp;lt;= 365&lt;/li&gt;
&lt;li&gt;종료 날짜 1 &amp;lt;= E &amp;lt;= 365&lt;/li&gt;
&lt;/ul&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;핵심 1. 연속된 일정을 순서대로 처리해야한다.&lt;/li&gt;
&lt;li&gt;핵심 2. 연속된 일정 중 하루에 가장 많은 일정의 수를 찾는다.&lt;/li&gt;
&lt;li&gt;핵심 3. 연속된 일정의 길이 * 일정 중 가장 많은 일정의 수로 끝나는 일정 별로 코팅지 면적을 구한다.&lt;br /&gt;핵심 1 - 그리디 특성, 핵심 2 - 구현 특성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고민할 포인트&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어려운 포인트. 하루에 가장 많은 일정의 수를 어떻게 구할 것인가?&lt;/li&gt;
&lt;li&gt;모든 날짜(day=365) 별로 몇개의 일정(N=1000)이 있는지 count한다.&lt;/li&gt;
&lt;li&gt;1000 * 365 = 3,650,000 &amp;lt; 1s&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1743350935702&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 Main {

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static int[] count = new int[366];
    static StringTokenizer st;

    public static void main(String[] args) throws IOException {
        int n = Integer.parseInt(br.readLine());
        for (int i = 0; i &amp;lt; n; i++) {
            st = new StringTokenizer(br.readLine());
            int firstDay = Integer.parseInt(st.nextToken());
            int lastDay = Integer.parseInt(st.nextToken());

            // 시작 일자부터 종료일자까지 일정 수 카운트
            for (int day = firstDay; day &amp;lt;= lastDay; day++) {
                count[day]++;
            }
        }

        int totalArea = 0;
        int width = 0;
        int height = 0;

        // 1일부터 365일까지 스캔하며 연속된 일정 그룹 찾기
        for (int day = 1; day &amp;lt;= 365; day++) {
            if (count[day] &amp;gt; 0) {
                // 현재 날짜에 일정이 있으면 폭 증가, 높이 업데이트
                width++;
                height = Math.max(height, count[day]);
            } else {
                // 현재 날짜에 일정이 없으면 이전 그룹의 면적 계산 후 초기화
                totalArea += width * height;
                width = 0;
                height = 0;
            }
        }

        totalArea += width * height;
        System.out.println(totalArea);
    }

}&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;a href=&quot;https://www.acmicpc.net/problem/20207&quot;&gt;https://www.acmicpc.net/problem/20207&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>그리디</category>
      <category>달력</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/101</guid>
      <comments>https://dev-dot.tistory.com/entry/BOJ-20207-%EB%8B%AC%EB%A0%A5#entry101comment</comments>
      <pubDate>Mon, 31 Mar 2025 01:00:05 +0900</pubDate>
    </item>
    <item>
      <title>말해보카 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EB%A7%90%ED%95%B4%EB%B3%B4%EC%B9%B4-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;11시 까지는 돌아올게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We'll be back ___ eleven.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;in - 시각이 아닌, 시간을 나타낼 때 사용된다. in one hours -&amp;gt; 1시간 안에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;on - on 뒤에는 보통 '요일' 또는 '날짜'가 나와야한다. 시간에는 on을 사용하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;at - 11시에 돌아온다는 의미가 된다.&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;정답은 by였다. ~ 까지는을 나타 낼 때는 by를 써야한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 걱정하지 마세요. 저도 저 자신은 지킬 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stop worrying so much. I can ___ myself.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;guard - guard는 누군가를 보호한다는 느낌으로 쓰는 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;safe - 안전한 이라는 형용사이므로 현재는 옳지 않은 문법이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;safety - 안전이라는 명사였다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;save - 구하다라는 뜻으로 위기에서 벗어나게 하는 느낌이었다.&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;정답은 protect였다. 스스로 보호하는 것은 protect다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 비행기가 한 시간 지연됐어.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Our flight was ___ an hour.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;late - 늦은이라는 형용사이며 ~ late by an hour처럼 써야 문법상 맞다.&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;정답은 delayed였다. 지연하는 delay라는 동사와 과거형&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 몇 주 동안 이 깜짝 파티를 준비해 왔어!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We've been ______ this suprise party for weeks!&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ready - 준비된이라는 형용사로 ready for this와 같이 이것을 위해 준비가 되었다는 의미로 써야하는 것이었다.&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;정답은 preparing이었다. 완전 처음보는 단어이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;prepare: 준비하다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>영어/오답노트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/100</guid>
      <comments>https://dev-dot.tistory.com/entry/%EB%A7%90%ED%95%B4%EB%B3%B4%EC%B9%B4-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8#entry100comment</comments>
      <pubDate>Sat, 4 Jan 2025 07:05:02 +0900</pubDate>
    </item>
    <item>
      <title>[Chrome Extension] 구글 딥다이브 크롬 확장 프로그램 제작기</title>
      <link>https://dev-dot.tistory.com/entry/Chrome-Extension-%EA%B5%AC%EA%B8%80-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%ED%81%AC%EB%A1%AC-%ED%99%95%EC%9E%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%A0%9C%EC%9E%91%EA%B8%B0</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 크롬 확장 프로그램을 제작하자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이걸 왜 만들었을까?&lt;br /&gt;구름 풀스택 과정 10기를 참여하면서 강의 리스트 중 중복되는 강좌가 있었다.&lt;br /&gt;중복되는 강좌를 식별하기 위해서 만들어봤다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKc6en/btsIXfNGVyJ/vZa2PzMfPRPQSC6pEcK8x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKc6en/btsIXfNGVyJ/vZa2PzMfPRPQSC6pEcK8x1/img.png&quot; data-alt=&quot;중복되지 않는 부분&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKc6en/btsIXfNGVyJ/vZa2PzMfPRPQSC6pEcK8x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKc6en%2FbtsIXfNGVyJ%2FvZa2PzMfPRPQSC6pEcK8x1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;233&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;중복되지 않는 부분&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LeT6Z/btsIX3MCelc/DZXR4nQwEFq0coABEkZR3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LeT6Z/btsIX3MCelc/DZXR4nQwEFq0coABEkZR3K/img.png&quot; data-alt=&quot;중복되는 부분&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LeT6Z/btsIX3MCelc/DZXR4nQwEFq0coABEkZR3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLeT6Z%2FbtsIX3MCelc%2FDZXR4nQwEFq0coABEkZR3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;180&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;중복되는 부분&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;How?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 docs를 찾아봐야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world?hl=ko&quot;&gt;https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world?hl=ko&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 잘 설명되어있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;요약해보자&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;manifest.json 이라는 파일과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;background.js, 그리고 동작을 할 js들이 필요하다.&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;자세한 코드는 git에 작성해두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 리팩토링을 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/groom-study-team1-project/chrome-extension&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/groom-study-team1-project/chrome-extension&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1723040812592&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - groom-study-team1-project/chrome-extension&quot; data-og-description=&quot;Contribute to groom-study-team1-project/chrome-extension development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/groom-study-team1-project/chrome-extension&quot; data-og-url=&quot;https://github.com/groom-study-team1-project/chrome-extension&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dthh4X/hyWKzdw9e1/4JFqDvGslVShH5EZrXNm61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/groom-study-team1-project/chrome-extension&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/groom-study-team1-project/chrome-extension&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dthh4X/hyWKzdw9e1/4JFqDvGslVShH5EZrXNm61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - groom-study-team1-project/chrome-extension&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to groom-study-team1-project/chrome-extension development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>java script</category>
      <category>js</category>
      <category>개발</category>
      <category>구름</category>
      <category>딥다이브</category>
      <category>웹</category>
      <category>인프런</category>
      <category>카카오</category>
      <category>크롬 확장</category>
      <category>프론트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/99</guid>
      <comments>https://dev-dot.tistory.com/entry/Chrome-Extension-%EA%B5%AC%EA%B8%80-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%ED%81%AC%EB%A1%AC-%ED%99%95%EC%9E%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%A0%9C%EC%9E%91%EA%B8%B0#entry99comment</comments>
      <pubDate>Wed, 7 Aug 2024 23:27:40 +0900</pubDate>
    </item>
    <item>
      <title>[React] 환경설정</title>
      <link>https://dev-dot.tistory.com/entry/React-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;원래 리액트는 웹팩이라는 Bundler로 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 강의는 리액트 문법과 리액트를 이해하기 위함이므로 React를 실제로 사용하는 환경설정은 하지 않는다.&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. React&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;리액트를 사용하기 위해서 기본적으로 환경설정이 되어야하는데 리액트에서 제공하는 개발용 cdn 링크가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1722758237761&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script crossorigin src=&quot;https://unpkg.com/react@17/umd/react.development.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&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;figure id=&quot;og_1722758294583&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;CDN 링크 &amp;ndash; React&quot; data-og-description=&quot;A JavaScript library for building user interfaces&quot; data-og-host=&quot;ko.legacy.reactjs.org&quot; data-og-source-url=&quot;https://ko.legacy.reactjs.org/docs/cdn-links.html&quot; data-og-url=&quot;https://ko.legacy.reactjs.org/docs/cdn-links.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Xzdx8/hyWKwUBaxg/mEazhsKkr4wgBm7c4cj58k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bpzAiS/hyWGQ8hesi/fq5ApbHfN123WJApkIRkM1/img.png?width=350&amp;amp;height=233&amp;amp;face=0_0_350_233&quot;&gt;&lt;a href=&quot;https://ko.legacy.reactjs.org/docs/cdn-links.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.legacy.reactjs.org/docs/cdn-links.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Xzdx8/hyWKwUBaxg/mEazhsKkr4wgBm7c4cj58k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bpzAiS/hyWGQ8hesi/fq5ApbHfN123WJApkIRkM1/img.png?width=350&amp;amp;height=233&amp;amp;face=0_0_350_233');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CDN 링크 &amp;ndash; React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A JavaScript library for building user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.legacy.reactjs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 배포까지 할 내용이 아니므로 강의와 동일하게 cdn을 이용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react.js 는 react 기능인 컴포넌트, 가상돔 등을 지원한다.&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;2. React-Dom&lt;/p&gt;
&lt;pre id=&quot;code_1722758394279&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script crossorigin src=&quot;https://unpkg.com/react-dom@17/umd/react-dom.development.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&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;React Dom은 가상 DOM을 실제 DOM에 렌더링 하는 작업과 같이 렌더링과 관련된 부가적인 기능을 수행해준다.&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;3. Babel.js&lt;/p&gt;
&lt;pre id=&quot;code_1722760472565&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&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;react에서는 JSX를 지원하는데 JavascriptXML로 HTML의 태그처럼 사용할 수 있는 문법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;babel.js가 JSX를 js로 변환해주고 es6를 지원하고 다양한 기능을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 JSX를 js로 변환해주면서 develop 환경에서 react를 사용하기 더욱 편리해지므로 babel.js를 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1722760672907&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &amp;lt;script type=&quot;text/babel&quot; src=&quot;js/main.js&quot; data-type=&quot;module&quot; data-presets=&quot;react&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react를 사용하려면 preset을 설정한다.&lt;/p&gt;</description>
      <category>JavaScript/React</category>
      <category>Babel</category>
      <category>CDN</category>
      <category>component</category>
      <category>react</category>
      <category>react-dom</category>
      <category>Virtual Dom</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/98</guid>
      <comments>https://dev-dot.tistory.com/entry/React-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95#entry98comment</comments>
      <pubDate>Sun, 4 Aug 2024 17:38:44 +0900</pubDate>
    </item>
    <item>
      <title>[React] Intro</title>
      <link>https://dev-dot.tistory.com/entry/React-Intro</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 크게 세가지 개념이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Reactive&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Virtual DOM&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Component&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;Reactive는 특정 값에 의존해 자동으로 반응하는 것을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vanila js로 검색 서비스를 만들면서 값을 변경하게 되면(검색 등) 다시 rendering을 하는 과정이 필요했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 리액트는 값을 변경하면 다시 rendering 할 필요가 없도록 설계되었다.&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;react는 DOM API를 호출하면서 성능 저하가 발생하는 문제를 해결하기 위해 Virtual DOM을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Virtual DOM에서 변경된 부분을 확인하고 바뀐 부분만 확인하여 DOM에 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 특성 때문에 reactive 하다고 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 참고하면 좋은 예시 영상이다.&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=BYbgopx44vo&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/ctvwXj/hyWKB2sD4B/mrYXdEURNpnD4mNkuznJU1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;React and the Virtual DOM&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/BYbgopx44vo&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;https://www.youtube.com/watch?v=BYbgopx44vo&lt;/figcaption&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;Component는 뒤에 작성.&lt;/p&gt;</description>
      <category>JavaScript/React</category>
      <category>component</category>
      <category>Dom</category>
      <category>react</category>
      <category>Reactive</category>
      <category>Virtual Dom</category>
      <category>리액트</category>
      <category>웹 프론트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/97</guid>
      <comments>https://dev-dot.tistory.com/entry/React-Intro#entry97comment</comments>
      <pubDate>Sat, 3 Aug 2024 00:30:53 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila js] 최근 검색 구현하기</title>
      <link>https://dev-dot.tistory.com/entry/Vanila-js-%EC%B5%9C%EA%B7%BC-%EA%B2%80%EC%83%89-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;history.gif&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;663&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GWXVY/btsIUktVKZ6/ENyqptcltQkd7LieOnTJQ0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GWXVY/btsIUktVKZ6/ENyqptcltQkd7LieOnTJQ0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GWXVY/btsIUktVKZ6/ENyqptcltQkd7LieOnTJQ0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/GWXVY/btsIUktVKZ6/ENyqptcltQkd7LieOnTJQ0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;373&quot; height=&quot;663&quot; data-filename=&quot;history.gif&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;663&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;View&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722603555532&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class HistoryListView extends KeywordListView {
    
    constructor() {
        super(qs(&quot;#history-list-view&quot;), new Template());
    }

    bindEvents() {}

    handleClickRemoveButton() {}

}&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;HistoryListView를 보면 KeywordListView 와 매우 유사하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천검색과 차별점을 생각하면, 검색기록을 지우는 작업이 추가로 수행되니까. 새로운 이벤트를 바인딩 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또, KeywordListView를 상속받으므로 KeywordListView의 생성자의 구조 변경이 발생한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Controller&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722603887202&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Controller {

  constructor(store, {searchFormView, searchResultView, tabView, keywordListView, historyListView}) {
    this.store = store;
    
    this.searchFormView = searchFormView;
    this.searchResultView = searchResultView;
    this.tabView = tabView;
    this.keywordListView = keywordListView;
    this.historyListView = historyListView;

    this.subscribeViewEvents();
    this.render();
  }
  
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히, Controller에도 historyListView 에 대한 의존성을 주입해주어야 하고 체이닝된 on method로 이벤트를 캐치해서 처리해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가할 기능은 렌더링 시 historyView를 보여주고 숨기는 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 검색어 제거시 지운 데이터를 렌더링 하는 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색시 최근 검색어에 추가하는 기능&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Model&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722604181575&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  search(keyword) {
    this.searchKeyword = keyword;
    this.searchResult = this.storage.productData.filter((product) =&amp;gt; 
      product.name.includes(keyword)
    );
    this.addHistory(keyword);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model에는 검색시 최근 검색 내역을 지우는 removeHistory 비즈니스 로직과 추가하는 addHistory 비즈니스 로직이 생성된다. Model은 persist layer 이므로 storage와 가장 밀접하기 때문이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Quest&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Q. 검색 시 최근 검색내역 추가하기&lt;/p&gt;
&lt;pre id=&quot;code_1722604323860&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Model
addHistory(keyword) {
    const alreadySearch = this.storage.historyData.some((history) =&amp;gt; history.keyword === keyword);
    if (alreadySearch) {
      this.removeHistory(keyword);
    }
    const id = createNextId(this.storage.historyData);
    const date = new Date();
    this.storage.historyData.push({id, keyword, date});
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller에서 store의 search 비즈니스 로직을 통해 검색을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 store의 search가 실행될 때, 검색 기록을 추가하는 비즈니스 로직을 추가하기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 강사님과 동일했고 utility를 잘 살펴보면서 createNextId 메소드까지 사용한 부분이 참 잘한 것 같다.&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>java script</category>
      <category>react</category>
      <category>vanila</category>
      <category>개발</category>
      <category>구름</category>
      <category>리액트</category>
      <category>바닐라 js</category>
      <category>웹 프론트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/96</guid>
      <comments>https://dev-dot.tistory.com/entry/Vanila-js-%EC%B5%9C%EA%B7%BC-%EA%B2%80%EC%83%89-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry96comment</comments>
      <pubDate>Fri, 2 Aug 2024 22:14:07 +0900</pubDate>
    </item>
    <item>
      <title>Day1. Ai와의 대화</title>
      <link>https://dev-dot.tistory.com/entry/Day1-Ai%EC%99%80%EC%9D%98-%EB%8C%80%ED%99%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘의&amp;nbsp;질문&amp;nbsp; &lt;br /&gt;ai:&amp;nbsp;What&amp;nbsp;is&amp;nbsp;your&amp;nbsp;favorite&amp;nbsp;hobby&amp;nbsp;and&amp;nbsp;why&amp;nbsp;do&amp;nbsp;you&amp;nbsp;enjoy&amp;nbsp;it? &lt;br /&gt;me:&amp;nbsp;I&amp;nbsp;like&amp;nbsp;watching&amp;nbsp;youtube,&amp;nbsp;because&amp;nbsp;i&amp;nbsp;can&amp;nbsp;not&amp;nbsp;thinking&amp;nbsp;in&amp;nbsp;watching&amp;nbsp;youtube. &lt;br /&gt;-&amp;gt;&amp;nbsp;&amp;ldquo;I&amp;nbsp;like&amp;nbsp;watching&amp;nbsp;YouTube&amp;nbsp;because&amp;nbsp;I&amp;nbsp;don&amp;rsquo;t&amp;nbsp;have&amp;nbsp;to&amp;nbsp;think&amp;nbsp;while&amp;nbsp;watching&amp;nbsp;it.&amp;rdquo; &lt;br /&gt;1.&amp;nbsp;can&amp;nbsp;뒤에는&amp;nbsp;동사&amp;nbsp;원형이&amp;nbsp;와야한다.&amp;nbsp; &lt;br /&gt;2.&amp;nbsp;in&amp;nbsp;은&amp;nbsp;문법상&amp;nbsp;옳지&amp;nbsp;않다&amp;nbsp;~&amp;nbsp;동안&amp;nbsp;이라는&amp;nbsp;while을&amp;nbsp;사용하자. &lt;br /&gt;3.&amp;nbsp;dont'&amp;nbsp;have&amp;nbsp;to&amp;nbsp;think&amp;nbsp;는&amp;nbsp;생각할&amp;nbsp;필요가&amp;nbsp;없다는&amp;nbsp;의미를&amp;nbsp;명확히&amp;nbsp;전달한다. &lt;br /&gt;4.&amp;nbsp;앞에&amp;nbsp;Youtube라는&amp;nbsp;것을&amp;nbsp;설명했으므로&amp;nbsp;it으로&amp;nbsp;표현해도&amp;nbsp;된다. &lt;br /&gt;&lt;br /&gt;ai:&amp;nbsp;What&amp;nbsp;kind&amp;nbsp;of&amp;nbsp;videos&amp;nbsp;do&amp;nbsp;you&amp;nbsp;usually&amp;nbsp;watch&amp;nbsp;on&amp;nbsp;YouTube? &lt;br /&gt;me:&amp;nbsp;hmm..&amp;nbsp;I&amp;nbsp;usually&amp;nbsp;watching&amp;nbsp;박진우&amp;nbsp;or&amp;nbsp;입질의&amp;nbsp;추억,&amp;nbsp;박진우's&amp;nbsp;youtube&amp;nbsp;content&amp;nbsp;is&amp;nbsp;travel&amp;nbsp;and&amp;nbsp;입질의&amp;nbsp;추억's&amp;nbsp;youtube&amp;nbsp;content&amp;nbsp;is&amp;nbsp;fishing&amp;nbsp;and&amp;nbsp;cooking&amp;nbsp;fish&amp;nbsp;so,&amp;nbsp;i&amp;nbsp;like&amp;nbsp;those&amp;nbsp;and&amp;nbsp;subscribe&amp;nbsp;too. &lt;br /&gt;-&amp;gt;&amp;nbsp;I&amp;nbsp;usually&amp;nbsp;watch&amp;nbsp;박진우&amp;nbsp;and&amp;nbsp;입질의&amp;nbsp;추억.&amp;nbsp;박진우&amp;rsquo;s&amp;nbsp;YouTube&amp;nbsp;content&amp;nbsp;is&amp;nbsp;about&amp;nbsp;travel,&amp;nbsp;and&amp;nbsp;입질의&amp;nbsp;추억&amp;rsquo;s&amp;nbsp;content&amp;nbsp;is&amp;nbsp;about&amp;nbsp;fishing&amp;nbsp;and&amp;nbsp;cooking&amp;nbsp;fish.&amp;nbsp;So,&amp;nbsp;I&amp;nbsp;like&amp;nbsp;them&amp;nbsp;and&amp;nbsp;have&amp;nbsp;subscribed&amp;nbsp;to&amp;nbsp;their&amp;nbsp;channels. &lt;br /&gt;1.&amp;nbsp;현재&amp;nbsp;시제에&amp;nbsp;맞게&amp;nbsp;usually&amp;nbsp;watch를&amp;nbsp;사용해야한다. &lt;br /&gt;2.&amp;nbsp;콘텐츠를&amp;nbsp;설명할&amp;nbsp;때,&amp;nbsp;about을&amp;nbsp;사용해서&amp;nbsp;더&amp;nbsp;명확한&amp;nbsp;표현을&amp;nbsp;했다. &lt;br /&gt;3.&amp;nbsp;사람을&amp;nbsp;지칭할&amp;nbsp;때&amp;nbsp;those가&amp;nbsp;아니라&amp;nbsp;them을&amp;nbsp;써야한다. &lt;br /&gt;4.&amp;nbsp;have&amp;nbsp;subscreibed&amp;nbsp;구독을&amp;nbsp;했다라는&amp;nbsp;표현에&amp;nbsp;더&amp;nbsp;잘&amp;nbsp;어울린다. &lt;br /&gt;5.&amp;nbsp;to&amp;nbsp;their&amp;nbsp;channels&amp;nbsp;대상을&amp;nbsp;표현해준다. &lt;br /&gt;&lt;br /&gt;ai:&amp;nbsp;What&amp;nbsp;is&amp;nbsp;your&amp;nbsp;favorite&amp;nbsp;place&amp;nbsp;you&amp;nbsp;have&amp;nbsp;traveled&amp;nbsp;to,&amp;nbsp;and&amp;nbsp;why&amp;nbsp;did&amp;nbsp;you&amp;nbsp;like&amp;nbsp;it? &lt;br /&gt;me:&amp;nbsp;do&amp;nbsp;you&amp;nbsp;know&amp;nbsp;합천?&amp;nbsp;I&amp;nbsp;did&amp;nbsp;go&amp;nbsp;to&amp;nbsp;합천&amp;nbsp;with&amp;nbsp;my&amp;nbsp;highschool&amp;nbsp;friends.&amp;nbsp;so,&amp;nbsp;i&amp;nbsp;have&amp;nbsp;a&amp;nbsp;good&amp;nbsp;memory&amp;nbsp;additional&amp;nbsp;i&amp;nbsp;don't&amp;nbsp;like&amp;nbsp;out&amp;nbsp;of&amp;nbsp;the&amp;nbsp;home,&amp;nbsp;but&amp;nbsp;i&amp;nbsp;out&amp;nbsp;of&amp;nbsp;the&amp;nbsp;hom&amp;nbsp;for&amp;nbsp;my&amp;nbsp;friends.&amp;nbsp;and&amp;nbsp;you? &lt;br /&gt;-&amp;gt;&amp;nbsp;Do&amp;nbsp;you&amp;nbsp;know&amp;nbsp;Hapcheon?&amp;nbsp;I&amp;nbsp;went&amp;nbsp;to&amp;nbsp;Hapcheon&amp;nbsp;with&amp;nbsp;my&amp;nbsp;high&amp;nbsp;school&amp;nbsp;friends,&amp;nbsp;so&amp;nbsp;I&amp;nbsp;have&amp;nbsp;good&amp;nbsp;memories&amp;nbsp;from&amp;nbsp;there.&amp;nbsp;Additionally,&amp;nbsp;I&amp;nbsp;don&amp;rsquo;t&amp;nbsp;usually&amp;nbsp;like&amp;nbsp;going&amp;nbsp;out,&amp;nbsp;but&amp;nbsp;thanks&amp;nbsp;to&amp;nbsp;my&amp;nbsp;friends,&amp;nbsp;I&amp;nbsp;was&amp;nbsp;able&amp;nbsp;to&amp;nbsp;go&amp;nbsp;out.&amp;nbsp;How&amp;nbsp;about&amp;nbsp;you? &lt;br /&gt;1.&amp;nbsp;did&amp;nbsp;go&amp;nbsp;to&amp;nbsp;보다는&amp;nbsp;went&amp;nbsp;to가&amp;nbsp;더&amp;nbsp;자연스럽다. &lt;br /&gt;2.&amp;nbsp;memories로&amp;nbsp;복수형으로&amp;nbsp;표현하고&amp;nbsp;어디에서&amp;nbsp;좋은&amp;nbsp;추억이&amp;nbsp;있는지&amp;nbsp;명확히&amp;nbsp;표현한다. &lt;br /&gt;3.&amp;nbsp;추가적으로를&amp;nbsp;표현할&amp;nbsp;때는&amp;nbsp;Additionally,&amp;nbsp;부사로&amp;nbsp;형용사&amp;nbsp;+&amp;nbsp;ly &lt;br /&gt;4.&amp;nbsp;i&amp;nbsp;don't&amp;nbsp;usually&amp;nbsp;like&amp;nbsp;-&amp;nbsp;usually가&amp;nbsp;빈도&amp;nbsp;부사로&amp;nbsp;사용되어&amp;nbsp;동사&amp;nbsp;앞에&amp;nbsp;위치한다. &lt;br /&gt;5.&amp;nbsp;out&amp;nbsp;of&amp;nbsp;the&amp;nbsp;보다는&amp;nbsp;going&amp;nbsp;out을&amp;nbsp;쓰면&amp;nbsp;깔끔해진다. &lt;br /&gt;6.&amp;nbsp;친구들한테&amp;nbsp;고맙다&amp;nbsp;나갈&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;해줘서라는&amp;nbsp;표현으로&amp;nbsp;수정 &lt;br /&gt;&lt;br /&gt;ai:&amp;nbsp;My&amp;nbsp;favorite&amp;nbsp;place&amp;nbsp;I&amp;rsquo;ve&amp;nbsp;traveled&amp;nbsp;to&amp;nbsp;is&amp;nbsp;Kyoto,&amp;nbsp;Japan.&amp;nbsp;I&amp;nbsp;loved&amp;nbsp;the&amp;nbsp;beautiful&amp;nbsp;temples&amp;nbsp;and&amp;nbsp;the&amp;nbsp;peaceful&amp;nbsp;atmosphere.&amp;nbsp;Have&amp;nbsp;you&amp;nbsp;ever&amp;nbsp;been&amp;nbsp;to&amp;nbsp;Japan? &lt;br /&gt;me:&amp;nbsp;No&amp;nbsp;I&amp;nbsp;hadn't&amp;nbsp;went&amp;nbsp;to&amp;nbsp;Japan.&amp;nbsp;But,&amp;nbsp;I&amp;nbsp;like&amp;nbsp;Japan's&amp;nbsp;anymation.&amp;nbsp;So,&amp;nbsp;I&amp;nbsp;know&amp;nbsp;beautiful&amp;nbsp;temples&amp;nbsp;and&amp;nbsp;the&amp;nbsp;peaceful&amp;nbsp;atmosphere&amp;nbsp;in&amp;nbsp;Japan.&amp;nbsp;And&amp;nbsp;Japanese&amp;nbsp;are&amp;nbsp;so&amp;nbsp;kind.&amp;nbsp;there&amp;nbsp;are&amp;nbsp;very&amp;nbsp;hard&amp;nbsp;rules&amp;nbsp;and&amp;nbsp;예의바르다.&amp;nbsp;How&amp;nbsp;think&amp;nbsp;about&amp;nbsp;you&amp;nbsp;Korea?&amp;nbsp; &lt;br /&gt;-&amp;gt;&amp;nbsp;No,&amp;nbsp;I&amp;nbsp;haven&amp;rsquo;t&amp;nbsp;been&amp;nbsp;to&amp;nbsp;Japan.&amp;nbsp;But&amp;nbsp;I&amp;nbsp;like&amp;nbsp;Japanese&amp;nbsp;animation,&amp;nbsp;so&amp;nbsp;I&amp;nbsp;know&amp;nbsp;about&amp;nbsp;the&amp;nbsp;beautiful&amp;nbsp;temples&amp;nbsp;and&amp;nbsp;the&amp;nbsp;peaceful&amp;nbsp;atmosphere&amp;nbsp;in&amp;nbsp;Japan.&amp;nbsp;Also,&amp;nbsp;Japanese&amp;nbsp;people&amp;nbsp;are&amp;nbsp;very&amp;nbsp;kind.&amp;nbsp;They&amp;nbsp;follow&amp;nbsp;strict&amp;nbsp;rules&amp;nbsp;and&amp;nbsp;are&amp;nbsp;very&amp;nbsp;polite.&amp;nbsp;What&amp;nbsp;do&amp;nbsp;you&amp;nbsp;think&amp;nbsp;about&amp;nbsp;Korea? &lt;br /&gt;1.&amp;nbsp;haven't&amp;nbsp;been&amp;nbsp;을&amp;nbsp;사용해서&amp;nbsp;현재&amp;nbsp;완료&amp;nbsp;시제를&amp;nbsp;맞춘다. &lt;br /&gt;2.&amp;nbsp;Japan's&amp;nbsp;보다는&amp;nbsp;Japanese,&amp;nbsp;Japanese&amp;nbsp;보다는&amp;nbsp;Japanese&amp;nbsp;people &lt;br /&gt;3.&amp;nbsp;~한&amp;nbsp;것을&amp;nbsp;알고&amp;nbsp;있다&amp;nbsp;-&amp;gt;&amp;nbsp;~에&amp;nbsp;대해&amp;nbsp;알고&amp;nbsp;있다.&amp;nbsp;-&amp;gt;&amp;nbsp;about을&amp;nbsp;붙이자. &lt;br /&gt;4.&amp;nbsp;And&amp;nbsp;보다는&amp;nbsp;Also가&amp;nbsp;더&amp;nbsp;적합하다. &lt;br /&gt;5.&amp;nbsp;follow&amp;nbsp;strict로&amp;nbsp;규칙을&amp;nbsp;엄격하게&amp;nbsp;지킨다를&amp;nbsp;표현할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;6.&amp;nbsp;polite라는&amp;nbsp;단어&amp;nbsp;획득&amp;nbsp;:&amp;nbsp;예의&amp;nbsp;바른 &lt;br /&gt;7.&amp;nbsp;What&amp;nbsp;do&amp;nbsp;you&amp;nbsp;think&amp;nbsp;가&amp;nbsp;올바른&amp;nbsp;표현이다.&amp;nbsp;How는&amp;nbsp;방법,&amp;nbsp;상태등을&amp;nbsp;묻고,&amp;nbsp;What은&amp;nbsp;의견을&amp;nbsp;묻는다 &lt;br /&gt;&lt;br /&gt;ai:&amp;nbsp;I&amp;nbsp;think&amp;nbsp;Korea&amp;nbsp;is&amp;nbsp;a&amp;nbsp;wonderful&amp;nbsp;country&amp;nbsp;with&amp;nbsp;a&amp;nbsp;rich&amp;nbsp;culture&amp;nbsp;and&amp;nbsp;history.&amp;nbsp;The&amp;nbsp;food&amp;nbsp;is&amp;nbsp;amazing,&amp;nbsp;and&amp;nbsp;people&amp;nbsp;are&amp;nbsp;very&amp;nbsp;friendly&amp;nbsp;and&amp;nbsp;welcoming.&amp;nbsp;I&amp;nbsp;also&amp;nbsp;admire&amp;nbsp;the&amp;nbsp;technological&amp;nbsp;advancements&amp;nbsp;and&amp;nbsp;the&amp;nbsp;beautiful&amp;nbsp;landscapes.&amp;nbsp;Have&amp;nbsp;you&amp;nbsp;traveled&amp;nbsp;to&amp;nbsp;any&amp;nbsp;other&amp;nbsp;countries? &lt;br /&gt;me:&amp;nbsp;Thank&amp;nbsp;you&amp;nbsp;so&amp;nbsp;much&amp;nbsp;about&amp;nbsp;Korea&amp;nbsp;from&amp;nbsp;Korean,&amp;nbsp;I&amp;nbsp;agree&amp;nbsp;to&amp;nbsp;Your&amp;nbsp;said.&amp;nbsp;Korea&amp;nbsp;is&amp;nbsp;big&amp;nbsp;culture&amp;nbsp;so&amp;nbsp;we&amp;nbsp;saying&amp;nbsp;K-pop.&amp;nbsp;and&amp;nbsp;our&amp;nbsp;technology&amp;nbsp;is&amp;nbsp;the&amp;nbsp;fastly&amp;nbsp;develop.&amp;nbsp;re&amp;nbsp;say&amp;nbsp;thanks&amp;nbsp;from&amp;nbsp;Korean.&amp;nbsp;and&amp;nbsp;I&amp;nbsp;have&amp;nbsp;been&amp;nbsp;Philippines.&amp;nbsp;but&amp;nbsp;i&amp;nbsp;will&amp;nbsp;say&amp;nbsp;next&amp;nbsp;chance&amp;nbsp;to&amp;nbsp;about&amp;nbsp;specific&amp;nbsp;Philippines&amp;nbsp;story.&amp;nbsp;Today&amp;nbsp;conversation&amp;nbsp;is&amp;nbsp;done. &lt;br /&gt;-&amp;gt;&amp;nbsp;Thank&amp;nbsp;you&amp;nbsp;so&amp;nbsp;much&amp;nbsp;for&amp;nbsp;your&amp;nbsp;kind&amp;nbsp;words&amp;nbsp;about&amp;nbsp;Korea.&amp;nbsp;As&amp;nbsp;a&amp;nbsp;Korean,&amp;nbsp;I&amp;nbsp;really&amp;nbsp;appreciate&amp;nbsp;it.&amp;nbsp;I&amp;nbsp;agree&amp;nbsp;with&amp;nbsp;what&amp;nbsp;you&amp;nbsp;said.&amp;nbsp;Korea&amp;nbsp;has&amp;nbsp;a&amp;nbsp;rich&amp;nbsp;culture,&amp;nbsp;which&amp;nbsp;we&amp;nbsp;often&amp;nbsp;refer&amp;nbsp;to&amp;nbsp;as&amp;nbsp;K-pop.&amp;nbsp;Our&amp;nbsp;technology&amp;nbsp;is&amp;nbsp;also&amp;nbsp;developing&amp;nbsp;rapidly.&amp;nbsp;Once&amp;nbsp;again,&amp;nbsp;thank&amp;nbsp;you&amp;nbsp;on&amp;nbsp;behalf&amp;nbsp;of&amp;nbsp;Koreans.&amp;nbsp;I&amp;nbsp;have&amp;nbsp;been&amp;nbsp;to&amp;nbsp;the&amp;nbsp;Philippines,&amp;nbsp;but&amp;nbsp;I&amp;nbsp;will&amp;nbsp;share&amp;nbsp;more&amp;nbsp;about&amp;nbsp;my&amp;nbsp;experience&amp;nbsp;there&amp;nbsp;next&amp;nbsp;time.&amp;nbsp;Let&amp;rsquo;s&amp;nbsp;end&amp;nbsp;our&amp;nbsp;conversation&amp;nbsp;here&amp;nbsp;for&amp;nbsp;today. &lt;br /&gt;&lt;br /&gt;1.&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;2.&amp;nbsp;한국인으로서는&amp;nbsp;As&amp;nbsp;a&amp;nbsp;Korean을&amp;nbsp;쓴다.&amp;nbsp;from은&amp;nbsp;한국인으로부터&amp;nbsp;라는&amp;nbsp;뜻이&amp;nbsp;된다. &lt;br /&gt;-&amp;gt;&amp;nbsp;한국인을&amp;nbsp;대표해서라고는&amp;nbsp;on&amp;nbsp;behalf&amp;nbsp;of&amp;nbsp;Koreans&amp;nbsp;라고&amp;nbsp;쓰는게&amp;nbsp;더&amp;nbsp;좋다. &lt;br /&gt;3.&amp;nbsp;I&amp;nbsp;really&amp;nbsp;appreciate&amp;nbsp;it,&amp;nbsp;진심으로&amp;nbsp;고맙다는&amp;nbsp;표현 &lt;br /&gt;4.&amp;nbsp;I&amp;nbsp;agree&amp;nbsp;with&amp;nbsp;what&amp;nbsp;you&amp;nbsp;said,&amp;nbsp;Your&amp;nbsp;said는&amp;nbsp;said가&amp;nbsp;동사이므로&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;없다.&amp;nbsp;What&amp;nbsp;you&amp;nbsp;said.로&amp;nbsp;쓴다. &lt;br /&gt;5.&amp;nbsp;agree&amp;nbsp;to&amp;nbsp;는&amp;nbsp;계획이나&amp;nbsp;제안에&amp;nbsp;동의할&amp;nbsp;때&amp;nbsp;쓴다.&amp;nbsp;agree&amp;nbsp;with&amp;nbsp;가&amp;nbsp;의견이나&amp;nbsp;발언에&amp;nbsp;동의할&amp;nbsp;때&amp;nbsp;쓴다. &lt;br /&gt;6.&amp;nbsp;big&amp;nbsp;culture&amp;nbsp;보다&amp;nbsp;rich&amp;nbsp;culture가&amp;nbsp;올바르고&amp;nbsp;문화는&amp;nbsp;갖고&amp;nbsp;있는&amp;nbsp;것이므로&amp;nbsp;have가&amp;nbsp;올바르다. &lt;br /&gt;7.&amp;nbsp;which&amp;nbsp;를&amp;nbsp;관계대명사로&amp;nbsp;사용하며&amp;nbsp;a&amp;nbsp;rich&amp;nbsp;culture를&amp;nbsp;재언급한다. &lt;br /&gt;8.&amp;nbsp;refer&amp;nbsp;to&amp;nbsp;as&amp;nbsp;:&amp;nbsp;~라고&amp;nbsp;부르다. &lt;br /&gt;9.&amp;nbsp;developing&amp;nbsp;rapidly&amp;nbsp;로&amp;nbsp;기술이&amp;nbsp;급속히&amp;nbsp;성장하고&amp;nbsp;있다고&amp;nbsp;표현하는게&amp;nbsp;좋음. &lt;br /&gt;10.&amp;nbsp;다시&amp;nbsp;한&amp;nbsp;번을&amp;nbsp;표현&amp;nbsp;할&amp;nbsp;떄는&amp;nbsp;Once&amp;nbsp;again을&amp;nbsp;쓰자. &lt;br /&gt;11.&amp;nbsp;have&amp;nbsp;been을&amp;nbsp;사용할&amp;nbsp;때는&amp;nbsp;전치사인&amp;nbsp;to를&amp;nbsp;쓰자. &lt;br /&gt;12.&amp;nbsp;다음&amp;nbsp;기회에&amp;nbsp;말한&amp;nbsp;다는&amp;nbsp;것은&amp;nbsp;'기회'가&amp;nbsp;아니고&amp;nbsp;'시간'에&amp;nbsp;초점을&amp;nbsp;둬야한다.&amp;nbsp;'기회'에&amp;nbsp;초점을&amp;nbsp;두면&amp;nbsp;말&amp;nbsp;그대로&amp;nbsp;기회가&amp;nbsp;주어졌을&amp;nbsp;떄만&amp;nbsp;말할&amp;nbsp;수&amp;nbsp;있기&amp;nbsp;때문이다. &lt;br /&gt;13.&amp;nbsp;말한다는&amp;nbsp;표현보다는&amp;nbsp;공유한다는&amp;nbsp;표현이&amp;nbsp;더&amp;nbsp;옳은&amp;nbsp;것&amp;nbsp;같다. &lt;br /&gt;14.&amp;nbsp;for&amp;nbsp;today,&amp;nbsp;날짜에&amp;nbsp;for이&amp;nbsp;들어가면&amp;nbsp;특정한&amp;nbsp;날을&amp;nbsp;지칭한다. &lt;br /&gt;15.&amp;nbsp;Let's는&amp;nbsp;let&amp;nbsp;us의&amp;nbsp;줄임말로&amp;nbsp;함께&amp;nbsp;어떤&amp;nbsp;행동을&amp;nbsp;행하고자&amp;nbsp;할&amp;nbsp;때&amp;nbsp;사용한다.&lt;/p&gt;</description>
      <category>영어/오답노트</category>
      <category>AI</category>
      <category>conversation</category>
      <category>English</category>
      <category>language</category>
      <category>대화</category>
      <category>문법</category>
      <category>영어</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/95</guid>
      <comments>https://dev-dot.tistory.com/entry/Day1-Ai%EC%99%80%EC%9D%98-%EB%8C%80%ED%99%94#entry95comment</comments>
      <pubDate>Fri, 2 Aug 2024 18:14:46 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila js] 키워드 검색 구현하기</title>
      <link>https://dev-dot.tistory.com/entry/Vanila-js-%ED%82%A4%EC%9B%8C%EB%93%9C-%EA%B2%80%EC%83%89-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;keyword-search.gif&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;817&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eEgYpL/btsIUmEJqfH/vVHwVGDjsqc7JsYafD9K91/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eEgYpL/btsIUmEJqfH/vVHwVGDjsqc7JsYafD9K91/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eEgYpL/btsIUmEJqfH/vVHwVGDjsqc7JsYafD9K91/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/eEgYpL/btsIUmEJqfH/vVHwVGDjsqc7JsYafD9K91/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;402&quot; height=&quot;817&quot; data-filename=&quot;keyword-search.gif&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;View&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722523524254&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class KeywordListView extends View {

    constructor() {
        super(qs('#keyword-list-view'));
        this.template = new Template();

        this.bindEvents();
    }

    show(data = []) {
    }

    bindEvents() {
    }

    handleClick(event) {
    }

}&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;앞선 기능들과 마찬가지로 keyword-list-view에 적용할 interface다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Result를 보면 키워드를 클릭하는 이벤트가 발생하니까 이벤트를 바인딩해주는 것이 필요하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keyword 목록들을 보여주어야 하므로 show() 메서드가 구현될 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Controller&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722523641407&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Controller {

  constructor(store, {searchFormView, searchResultView, tabView, keywordListView}) {
    this.store = store;
    
    this.searchFormView = searchFormView;
    this.searchResultView = searchResultView;
    this.tabView = tabView;
    this.keywordListView = keywordListView;

    this.subscribeViewEvents();
    this.render();
  }
  
}&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;앞선 포스트에서도 줄줄이 설명했듯이 당연히 View는 Controller에 의존되므로 keywordListView의 의존성이 추가됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 usbscribeViewEvents에서 클릭 이벤트가 처리될 것이고 render에는 keyword list를 렌더링하는 작업이 추가될 것으로 예상이 될 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Model&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722523849638&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Store {
  constructor(storage) {
    if (!storage) throw &quot;no storage&quot;;

    this.storage = storage;
    this.searchResult = [];
    this.searchKeyword = &quot;&quot;;
    this.selectedTab = TabType.KEYWORD;
  }
  
  getKeywordList() {} // 추가된 기능
  
}&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;Store 객체는 Persistence Layer와 밀접하므로 데이터 정보를 들고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 추천 검색어나 최신 검색어에 대한 정보가 저장된 storage는 Store에 의존되고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(첫 게시글부터 이런 템플릿을 맞추어서 작성했다면.. storage에 대한 설명을 충분히 했을텐데 안타깝다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722524043671&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const storage = {
  keywordData: [],
  historyData: [],
  productData: []
}&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;강사님 git이나 강의를 들으면 알 수 있겠지만, storage는 이런식으로 사용될 정보가 정적 데이터로 저장되어있다.&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;아, 그래서 이번 기능 구현에서는 추천 검색어에 대한 keyword들을 가져오기 위해 model 에서 storage에 접근해 keyword를 가져와야한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Quest&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q. keyword 클릭 시 검색 결과 불러오기&lt;/p&gt;
&lt;pre id=&quot;code_1722524272174&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// View
show(keyword) {
    this.inputElement.value = keyword;
    this.showResetButton(true);
}
    
// Controller
this.keywordListView
.on(&quot;@click&quot;, (event) =&amp;gt; {
  const keyword = event.detail.value;
  this.searchFormView.show(keyword);
  this.search(keyword);
});&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;나는 키워드를 클릭할 경우, View에서 텍스트 창에 글을 추가하고 reset button을 만들어주도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 조금 멍청했다. 작업은 아래와 같이 수행이 되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용자는 Keyword List View에서 검색을 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Controller로 처리를 해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 검색한 키워드가 Store에 저장이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 저장이 된 내용물을 View에 반영한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 내가 작성한 로직은 3번을 고려못한 것이 아쉬웠다. 이전에 작성한 search 메소드에서 Store 객체에 searchKeyword로 keyword 값을 전달하는데.. 이것을 이용해서 render 할 때, 추가하는 것이 더 깔끔해보였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 내 코드도 동작하지만 비슷한 기능들의 통합성이라고 해야할까.. 강의가 너무 괜찮다.&lt;/p&gt;
&lt;pre id=&quot;code_1722525239355&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  renderSearchResult() {
    this.searchFormView.show(this.store.searchKeyword);
    this.tabView.hide();
    this.keywordListView.hide();
    this.searchResultView.show(this.store.searchResult);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;.검색결과를 렌더링 하는 메소드의 응집도가 정말 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>goorm x kakao</category>
      <category>Inflean</category>
      <category>react</category>
      <category>vanila js</category>
      <category>Web Front</category>
      <category>리액트</category>
      <category>웹 프론트</category>
      <category>인프런</category>
      <category>자바 스크립트</category>
      <category>풀스택 10기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/94</guid>
      <comments>https://dev-dot.tistory.com/entry/Vanila-js-%ED%82%A4%EC%9B%8C%EB%93%9C-%EA%B2%80%EC%83%89-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry94comment</comments>
      <pubDate>Fri, 2 Aug 2024 00:15:21 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila js] 탭 구현하기</title>
      <link>https://dev-dot.tistory.com/entry/Vanila-js-%ED%83%AD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;tab.gif&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIxqq9/btsIRZ5oCUu/8cyM9MBvzD0HwQU1pU90j0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIxqq9/btsIRZ5oCUu/8cyM9MBvzD0HwQU1pU90j0/img.gif&quot; data-alt=&quot;tab 기능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIxqq9/btsIRZ5oCUu/8cyM9MBvzD0HwQU1pU90j0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cIxqq9/btsIRZ5oCUu/8cyM9MBvzD0HwQU1pU90j0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;307&quot; height=&quot;517&quot; data-filename=&quot;tab.gif&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;tab 기능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;View&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722496857193&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class TabView extends View {

    constructor() {
        super(qs('#tab-view'));
     
        this.template = new Template();
    }
    
    show() {}
    bindEvents() {}
    
}&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;정적 페이지의 tab-view id를 가진 태그에 작업을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Result와 같이 탭을 보여줄 기능과, 탭을 누르는 행위를 하는 기능이 필요&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Controller&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722497002579&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Controller {
  constructor(store, {searchFormView, searchResultView, tabView}) {
    this.store = store;
    
    this.searchFormView = searchFormView;
    this.searchResultView = searchResultView;
    this.tabView = tabView;

    this.subscribeViewEvents();
    this.render();
  }
}&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;Controller에는 View와 Model의 제어를 위해 당연히 tabView가 추가 되어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 View에서 구현한 tab을 보여주는 기능과 클릭과 같은 이벤트들을 처리하는 작업을 구현해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1722497100969&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  subscribeViewEvents() {
    this.tabView
    .on('@select', (event) =&amp;gt; this.select(event.detail.target));
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, tabView에서 select라는 이벤트가 발생했을 때, chaining 된 on method로 이벤트를 캐치하고 처리한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Model&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722497190625&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Store {
  constructor(storage) {
    if (!storage) throw &quot;no storage&quot;;

    this.storage = storage;
    this.searchResult = [];
    this.searchKeyword = &quot;&quot;;
    this.selectedTab = TabType.KEYWORD;
  }
}&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;Store Model 에서는 어떤 키워드를 선택했는지에 대한 정보를 담기 위한 selectedTab 변수가 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 처음, 렌더링 할 때 default로 추천검색어를 선택한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Quest&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Q. 각 탭을 클릭하면 탭 아래 내용이 변경되도록 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;우선, 강의의 챕터 상 탭 아래 내용은 tab-content로 다른 책임을 가지고 있으므로 잠시 비워둔다.&lt;/p&gt;
&lt;pre id=&quot;code_1722497641424&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    bindEvents() {
        on(this.element, &quot;click&quot;, event =&amp;gt; this.handleClick(event));
    }

    handleClick(event) {
        const { target } = event;
        
        this.emit(&quot;@select&quot;, { target });
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 TabView에서 클릭 이벤트가 발생하면 클릭한 주체를 @select 이벤트로 발행했다.&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;그리고 앞서 Controller에서 작성한, subscribeEvents 메소드에서 tabView로 부터 @select 이벤트가 발생하면 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller 입장에서, 어떤 태그를 클릭했는지 명확히 알 수 있다. (TabView에서 알려줌)&lt;/p&gt;
&lt;pre id=&quot;code_1722497829096&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  select(target) {
    const tab = target.dataset.tab;

    this.store.select(tab);
    this.tabView.show(this.store.selectedTab);
  }&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;그리고 target의 tab 정보를 가져와서 store의 selectedTab 변수로 지정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 tabView를 다시 렌더링 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강사님께서는 utility(helper.js)의 delegate를 사용하고 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1722498069695&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function delegate(target, eventName, selector, handler) {
  const emitEvent = (event) =&amp;gt; {
    const potentialElements = qsAll(selector, target);

    for (const potentialElement of potentialElements) {
      if (potentialElement === event.target) {
        return handler.call(event.target, event);
      }
    }
  };

  on(target, eventName, emitEvent);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 상위 tag의 모든 하위 요소를 다 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 상위 tag의 모든 하위 요소 중 브라우저에서 event가 발생한 요소와 같은 것을 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 상위 tag의 이벤트로 추가한다.&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;내 코드의 문제점은 li 태그 외에 다른 태그가 추가되었을 때도 이벤트가 발행된다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 작성한 코드에서 bindEvents만 delegate로 수정하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1722499525486&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;handleClick(event) {
    const tab = event.target.dataset.tab;
    this.emit(&quot;@tabchange&quot;, { tab });
}
 
this.tabView
.on('@tabchange', (event) =&amp;gt; {this.select(event.detail.tab);});
    
select(tab) {
    this.store.select(tab);
    this.tabView.show(this.store.selectedTab);
}&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;TabView에서 click event가 tab change만 존재하지 않고, 추가적인 event가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; event 발행 시 명확한 이벤트 명과 필요한 데이터를 가지고 발행한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Tip&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722501205997&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Template {
    getTabList() {
        return `
            &amp;lt;ul class=&quot;tabs&quot;&amp;gt;
                ${Object.values(TabType)
                .map(tabType =&amp;gt; ({ tabType, tabLabel: TabLabel[tabType] }))
                .map(this._getTab)
                .join(&quot;&quot;)}
            &amp;lt;/ul&amp;gt;
        `;
    }

    _getTab({tabType, tabLabel}) {
        return `
            &amp;lt;li data-tab=${tabType}&amp;gt;
                ${tabLabel}
            &amp;lt;/li&amp;gt;
        `;
    }
}&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;렌더링을 위한 Template 클래스에서 _getTap method로 map 함수를 돌리는 과정에서 $[tabLabel] 백틱 부분이 계속해서 undefined로 출력됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 js에서 중괄호, {}를 사용하면 파라미터 전달이 아니고 mapping이 되는 것이다. 즉, getTabList() 메소드에서 첫번 째 map 메소드에서 { tabType, tabLabel } 로 바꾸었고, 그 다음 map 메소드에서 _getTab으로 변환하는 중 tabLabel이 tabLable로 오타가 발생해서 매핑이 되지 않는 문제였다.&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;이 팁은 handleClick 메소드와 같이 작성할 때도 신경써야하는 부분이다.&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>java script</category>
      <category>react</category>
      <category>tab 구현</category>
      <category>vanila js</category>
      <category>개발</category>
      <category>리액트</category>
      <category>웹</category>
      <category>자바 스크립트</category>
      <category>탭 구현</category>
      <category>프론트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/93</guid>
      <comments>https://dev-dot.tistory.com/entry/Vanila-js-%ED%83%AD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry93comment</comments>
      <pubDate>Thu, 1 Aug 2024 17:07:51 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila js] 검색 결과 기능 구현</title>
      <link>https://dev-dot.tistory.com/entry/Vanila-js-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;View&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722412236856&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class SearchResultView extends View {
    constructor() {
        super(qs(&quot;#search-result-view&quot;));

        this.template = new Template();
    }

    show(data = []) {
        if (data.length &amp;gt; 0) {
            this.element.innerHTML = this.template.getList(data);
        } else {
            this.element.innerHTML = this. template.getEmptyMessage();
        }

        super.show();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 검색 결과 구현을 위해 정적 페이지에서 search-result-view를 생성하고 query selector로 호출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 SearchResultView의 element 변수는 검색 결과 태그의 정보를 갖게 된다.&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;Template은 class로 어떻게 렌더링 할 것인지에 대해 명시해둔 코드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Controller 에서의 작업을 마치고 View의 show 메서드로 렌더링을 할 것임을 알 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Controller&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722412808969&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Controller {
  constructor(store, {searchFormView, searchResultView}) {
    this.store = store;
    this.searchFormView = searchFormView;
    this.searchResultView = searchResultView;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 SearchResultView에 대한 의존성도 추가해준다.&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;앞서 검색 기능 구현하기에서 작성된, search()와 reset()의 서비스 로직을 완성하면 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Model&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722413583457&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Store {
  constructor(storage) {
    if (!storage) throw &quot;no storage&quot;;

    this.storage = storage;
    this.searchResult = [];
    this.searchKeyword = &quot;&quot;;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;searchKeyword와 searchResult를 담을 변수를 만들어주고 Business Logic을 작성해준다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Quest&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q. reset 기능 구현하기&lt;/p&gt;
&lt;pre id=&quot;code_1722413696046&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// controller
  reset() {
    this.store.reset();
    this.render();
  }
  
// model
  reset() {
    this.searchKeyword = &quot;&quot;;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강사님은 Controller reset() 메소드에 this.store.searchKeyword = &quot;&quot;를 추가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 keyword가 Store 라는 Model에 종속된 변수이므로 Store 객체에서 직접 접근하도록 인스턴스 메서드로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, 강사님은 searchResult 또한 빈 배열로 초기화하였는데, 나는 render() 작업에서 searchResult가 update 되므로 굳이 작성하지는 않았다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;search-result.gif&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZQz5d/btsIRfNYCI8/IHeha1v7gMRvUmuHS5gZyk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZQz5d/btsIRfNYCI8/IHeha1v7gMRvUmuHS5gZyk/img.gif&quot; data-alt=&quot;실행결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZQz5d/btsIRfNYCI8/IHeha1v7gMRvUmuHS5gZyk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cZQz5d/btsIRfNYCI8/IHeha1v7gMRvUmuHS5gZyk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;430&quot; data-filename=&quot;search-result.gif&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;607&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 이전 Post에서의 궁금했던 점 해결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller 에서 Service 로직을 작성한다.&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>FRONT</category>
      <category>It</category>
      <category>java script</category>
      <category>js</category>
      <category>react</category>
      <category>vanila</category>
      <category>web</category>
      <category>검색결과</category>
      <category>웹 프론트</category>
      <category>자바 스크립트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/92</guid>
      <comments>https://dev-dot.tistory.com/entry/Vanila-js-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84#entry92comment</comments>
      <pubDate>Wed, 31 Jul 2024 17:29:23 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila js] 검색 기능 구현하기</title>
      <link>https://dev-dot.tistory.com/entry/Vanila-js-%EA%B2%80%EC%83%89-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Branch - ready/search-form-1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞선 포스팅의 작업이 제대로 되었다면 main 브랜치에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. git checkout -b ready/search-form-1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 코드 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. git add .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. git commit -m &quot;feat: 내용&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. git push origin ready/search-form-1&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;777&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdMM1b/btsIReIb6Zn/xqryWl5OK1kz1TwxfT2yCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdMM1b/btsIReIb6Zn/xqryWl5OK1kz1TwxfT2yCk/img.png&quot; data-alt=&quot;PR&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdMM1b/btsIReIb6Zn/xqryWl5OK1kz1TwxfT2yCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdMM1b%2FbtsIReIb6Zn%2FxqryWl5OK1kz1TwxfT2yCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;936&quot; height=&quot;777&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;777&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PR&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 PR 날리고 Rebase Merge 하기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git bash에서 코드로 할 수도 있지만, 협업 중 코드 리뷰를 하는 과정이 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 직접 github 사이트에서 Merge하는 것에 익숙해지기&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;앞으로 모든 작업은 위 과정을 반복해서 branch를 업데이트 할 예정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722401970982&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// index.html
&amp;lt;script type=&quot;module&quot; src=&quot;./js/main.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    
// main.js
document.addEventListener(&quot;DOMContentLoaded&quot;, main);

function main() {}&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정적페이지에 module로 main.js가 추가된 것을 알 수 있다.&lt;br /&gt;즉, main의 코드는 맨 처음 index.html을 DOM에서 불러올 때, main.js에 작성된 코드들을 모두 불러온다.&lt;/li&gt;
&lt;li&gt;main.js 에서 dom이 load될 때, main method를 eventListener로 추가한다.&lt;/li&gt;
&lt;li&gt;closer 개념으로 main method는 하나의 instance가 되고 main method에서 작성된 코드에 계속해서 접근할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 뭐 작성할 코드가 있으면 main method에서 처리하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강사님은 이것을 MVC 패턴을 활용해서 처리했다.&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;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722405107948&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;클로저 - JavaScript | MDN&quot; data-og-description=&quot;클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/TSTgG/hyWGOvgLhR/f3KPsOOWT1SWZIDsE6jHF0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/TSTgG/hyWGOvgLhR/f3KPsOOWT1SWZIDsE6jHF0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;클로저 - JavaScript | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722405161817&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class SearchFormView extends View {
    constructor() {
        super(qs(&quot;#search-form-view&quot;));
        
        this.inputElement = qs(&quot;[type=text]&quot;, this.element);
        this.resetElement = qs(&quot;[type=reset]&quot;, this.element);

        this.showResetButton(false);
        this.bindEvents()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;View를 확장받는 검색 View를 살펴보자&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;1. 정적페이지에 작성된 검색 폼 태그를 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 해당 태그에 속해있는 녀석 중 type 속성이 text와 reset인 것을 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 그리고 해당 태그들에 대한 기능들을 작성한다. -&amp;gt; 기능별로 잘 분리된 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722405500903&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    bindEvents() {
        on(this.inputElement, &quot;keyup&quot;, () =&amp;gt; this.handleKeyup());
        on(this.element, &quot;submit&quot;, event =&amp;gt; this.handleSubmit(event));
        on(this.resetElement, &quot;click&quot;, () =&amp;gt; this.handleReset());
    }

    handleSubmit(event) {
        event.preventDefault();

        const {value} = this.inputElement;
        this.emit(&quot;@submit&quot;, {value});
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 각 메서드에 대한 event를 helper.js에서 utility로 구현한 on 메소드로 이벤트를 감지하고 핸들러 작업을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 HTML에는 특정 이벤트에 대한 작업이 되어있다. 추가적인 작업이나 기존 작업을 없앨 경우, 핸들러를 사용해야한다.&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;emit 또한, helper.js에서 구현된 utility이다.&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;pre id=&quot;code_1722405735449&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class Controller {
  constructor(store, {searchFormView}) {
    this.store = store;
    
    this.searchFormView = searchFormView;

    this.subscribeViewEvents();
  }

  subscribeViewEvents() {
    this.searchFormView
    .on('@submit', (event) =&amp;gt; this.search(event.detail.value))
    .on('@reset', () =&amp;gt; this.reset());
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;View에서 전달된 작업은 Controller에서 Catch하여 상세 작업을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;궁금한 점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Controller에서 Business Logic을 작성할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Model에서 Business Logic을 작성하고 Controller에서 store 객체를 이용해 서비스 작업을 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 그 다음 작업이 끝난 뒤 반환할 때는 View에게 다시 Event를 주는걸까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Controller에서 변화된 렌더링 작업을 할까?&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;퀘스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색어 Reset 버튼 클릭 시, 검색 내용 제거 및 검색어 지우는 작업&lt;/p&gt;
&lt;pre id=&quot;code_1722406860870&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// View

    bindEvents() {
        on(this.resetElement, &quot;click&quot;, () =&amp;gt; this.handleReset());
    }
    
    
    handleReset() {
        this.emit(&quot;@reset&quot;);
        this.showResetButton(false);
    }
    
 // Controller
 
  subscribeViewEvents() {
    this.searchFormView
    .on('@reset', () =&amp;gt; this.reset());
  }
  
  reset() {
    console.log(&quot;reset&quot;);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. input tag의 속성인 reset type은 HTML에서 제공하는 form data를 모두 지운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 그래서 따로 지우는 작업을 하지 않아도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이후 검색 내용을 지우기 위해서 Controller에서 작업이 발생할테니까, 이벤트를 핸들러로 바인딩해두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 바인딩된 핸들러 이벤트는 Controller에서 작업이 진행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 작업이 끝나면 View 단에서 보여진 Btn을 숨기기위해 showResetButton 메소드를 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722407020746&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    handleKeyup() {
        const {value} = this.inputElement;

        if (value.length &amp;lt;= 0) this.handleReset();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강사는 검색내용을 작성하다 지울 때도 Reset을 하도록 했다.&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>closer</category>
      <category>FRONT</category>
      <category>HTML</category>
      <category>java script</category>
      <category>js</category>
      <category>MDN</category>
      <category>react</category>
      <category>vanila</category>
      <category>web</category>
      <category>자바 스크립트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/91</guid>
      <comments>https://dev-dot.tistory.com/entry/Vanila-js-%EA%B2%80%EC%83%89-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry91comment</comments>
      <pubDate>Wed, 31 Jul 2024 15:25:59 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila.js] 사전 코드 이해하기</title>
      <link>https://dev-dot.tistory.com/entry/Vanilajs-%EC%82%AC%EC%A0%84-%EC%BD%94%EB%93%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;강사님이 미리 구현해 둔 서비스&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;branch : ready/scaffoding&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;In Memory DB
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;추천 검색어, 검색 기록, 상품 데이터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Utility
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시간관련 Util&lt;/li&gt;
&lt;li&gt;DOM Event를 활용한 Util&lt;/li&gt;
&lt;li&gt;기본적으로 JS에서 제공하는 기술들을 모듈화했다고 보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Model
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;이후에 비즈니스 로직 및 중요 로직이 담길 것으로 보임.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;View
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정적 페이지 정보를 렌더링(수정)하는 페이지&lt;/li&gt;
&lt;li&gt;Utility를 활용해 기본적인 기능이 제공된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Controller&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;View에 작성될 내용을 제어&lt;/li&gt;
&lt;li&gt;Model의 비즈니스 로직을 활용하거나 따로 서비스 로직을 작성할 듯&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>FRONT</category>
      <category>java script</category>
      <category>js</category>
      <category>react</category>
      <category>vanila</category>
      <category>web</category>
      <category>개발</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/90</guid>
      <comments>https://dev-dot.tistory.com/entry/Vanilajs-%EC%82%AC%EC%A0%84-%EC%BD%94%EB%93%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry90comment</comments>
      <pubDate>Wed, 31 Jul 2024 13:53:19 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila.js] 환경셋팅 1</title>
      <link>https://dev-dot.tistory.com/entry/%EC%9D%B8%ED%94%84%EB%9F%B0-%EB%A6%AC%EC%95%A1%ED%8A%B8-Vanila-js%EB%A1%9C-%EC%87%BC%ED%95%91%EB%AA%B0-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우아한 형제들에서 근무 중이신 프론트 개발자 김정환님의 강의를 기반으로 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프런 강의 제목은 '만들고 비교하며 학습하는 리액트'입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 강의는 깃을 사용하며 Branch별로 강의를 해주십니다.&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;학습을 하기 위해 먼저 git을 fork합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1266&quot; data-origin-height=&quot;667&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxZ6HU/btsISHCpyjd/3ypcNCISgRMmkCyOq9GgFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxZ6HU/btsISHCpyjd/3ypcNCISgRMmkCyOq9GgFK/img.png&quot; data-alt=&quot;김정환님 git&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxZ6HU/btsISHCpyjd/3ypcNCISgRMmkCyOq9GgFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxZ6HU%2FbtsISHCpyjd%2F3ypcNCISgRMmkCyOq9GgFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;510&quot; height=&quot;269&quot; data-origin-width=&quot;1266&quot; data-origin-height=&quot;667&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;김정환님 git&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/osFj6/btsIRx1z5CW/2wApbmpRnBkyL0e4Yv3BN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/osFj6/btsIRx1z5CW/2wApbmpRnBkyL0e4Yv3BN0/img.png&quot; data-alt=&quot;내 git repository&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/osFj6/btsIRx1z5CW/2wApbmpRnBkyL0e4Yv3BN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FosFj6%2FbtsIRx1z5CW%2F2wApbmpRnBkyL0e4Yv3BN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;624&quot; height=&quot;326&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;479&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내 git repository&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fork가 잘되었다면, 강사님이 만들어 둔 branch로 이동할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 fork한 내 레파지토리를 clone하고 해당 폴더로 이동해서 git bash를 실행합니다.&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. git remote add upstream &lt;a href=&quot;https://github.com/jeonghwan-kim/lecture-react.git&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/jeonghwan-kim/lecture-react.git&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. git fetch upstream&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. git checkout -f upstream/ready/scaffoding&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. git switch -c ready/scaffoding&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. git push origin ready/scaffoding&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oL11C/btsITaK4yLa/UDH9rbqOb0qSLb93s6lBtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oL11C/btsITaK4yLa/UDH9rbqOb0qSLb93s6lBtK/img.png&quot; data-alt=&quot;추가된 branch&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oL11C/btsITaK4yLa/UDH9rbqOb0qSLb93s6lBtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoL11C%2FbtsITaK4yLa%2FUDH9rbqOb0qSLb93s6lBtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;944&quot; height=&quot;387&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;추가된 branch&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방식으로 브랜치가 추가되었으면, main 브랜치도 추가 후 학습을 따라해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방식으로 현재 branch가 ready/scaffoding로 선택되어 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. git branch -M main&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. git push origin -u main&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 위 사진과 똑같이 main 브랜치도 추가됩니다.&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;이제 github remote repository 에서 settings에 들어갑니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bH1XOE/btsIRZQ6Zxo/s1J4THG4cckPYGVkaAOFR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bH1XOE/btsIRZQ6Zxo/s1J4THG4cckPYGVkaAOFR0/img.png&quot; data-alt=&quot;Github -&amp;amp;gt; Repository -&amp;amp;gt; Settings -&amp;amp;gt; General -&amp;amp;gt; Default Branch&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bH1XOE/btsIRZQ6Zxo/s1J4THG4cckPYGVkaAOFR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbH1XOE%2FbtsIRZQ6Zxo%2Fs1J4THG4cckPYGVkaAOFR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;784&quot; height=&quot;165&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;165&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Github -&amp;gt; Repository -&amp;gt; Settings -&amp;gt; General -&amp;gt; Default Branch&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main branch를 default로 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgYYYA/btsIQnFDMnF/uAKsCQvglKYY16fk6eF4e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgYYYA/btsIQnFDMnF/uAKsCQvglKYY16fk6eF4e1/img.png&quot; data-alt=&quot;updated repository&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgYYYA/btsIQnFDMnF/uAKsCQvglKYY16fk6eF4e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgYYYA%2FbtsIQnFDMnF%2FuAKsCQvglKYY16fk6eF4e1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;927&quot; height=&quot;606&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;updated repository&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 Clone coding 학습을 시작해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1722343888877&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[리액트 1부] 만들고 비교하며 학습하는 리액트 (React) 강의 | 김정환 - 인프런&quot; data-og-description=&quot;김정환 | 리액트는 실무에서 가장 많이 찾는 인기있는 프론트엔드 기술입니다. 리액트 기술을 이용해 어플리케이션을 빠르게 개발하고 유지 보수 가능한 코드를 만들어 보세요., 프론트 실무 최&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C-%ED%95%99%EC%8A%B5%ED%95%98%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8&quot; data-og-url=&quot;https://www.inflearn.com/course/만들면서-학습하는-리액트&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/TxcK0/hyWG1HU3fl/Thufr25Jhbmh30wO22D53K/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/mbDjT/hyWGSxsW34/vpHNxhkhB0MWI17wVo29K0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BslAe/hyWGZXExn8/rutwcB7hma7DyhaCYe91nK/img.png?width=736&amp;amp;height=479&amp;amp;face=0_0_736_479&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C-%ED%95%99%EC%8A%B5%ED%95%98%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C-%ED%95%99%EC%8A%B5%ED%95%98%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/TxcK0/hyWG1HU3fl/Thufr25Jhbmh30wO22D53K/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/mbDjT/hyWGSxsW34/vpHNxhkhB0MWI17wVo29K0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BslAe/hyWGZXExn8/rutwcB7hma7DyhaCYe91nK/img.png?width=736&amp;amp;height=479&amp;amp;face=0_0_736_479');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[리액트 1부] 만들고 비교하며 학습하는 리액트 (React) 강의 | 김정환 - 인프런&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;김정환 | 리액트는 실무에서 가장 많이 찾는 인기있는 프론트엔드 기술입니다. 리액트 기술을 이용해 어플리케이션을 빠르게 개발하고 유지 보수 가능한 코드를 만들어 보세요., 프론트 실무 최&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>FRONT</category>
      <category>inflearn</category>
      <category>js</category>
      <category>react</category>
      <category>vanila</category>
      <category>김정환</category>
      <category>리액트</category>
      <category>웹</category>
      <category>자바 스크립트</category>
      <category>프론트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/89</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%9D%B8%ED%94%84%EB%9F%B0-%EB%A6%AC%EC%95%A1%ED%8A%B8-Vanila-js%EB%A1%9C-%EC%87%BC%ED%95%91%EB%AA%B0-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry89comment</comments>
      <pubDate>Tue, 30 Jul 2024 21:51:58 +0900</pubDate>
    </item>
    <item>
      <title>[Vanila.js] 환경셋팅2</title>
      <link>https://dev-dot.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. VS 코드를 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Node.js를 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-1. npm --version 으로 환경변수 설치가 잘되었는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Git Bash를 설치한다. (선택, 프로젝트 관리하려면 설치)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. npx lite-server --baseDir &quot;폴더명&quot;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;or npx lite-server&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;※ 주의 (windows 환경)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js의 경로를 커스텀 영역에 설치 시, 실행이 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Ctrl + r -&amp;gt; %appdata% -&amp;gt; 새폴더 생성(이름: npm)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. System 환경변수에서 해당 node js의 custom 영역을 path 변수에 추가한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;285&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHhCeZ/btsIQEmJdqH/QTxIqtlhTeLZ5C5k6XsWhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHhCeZ/btsIQEmJdqH/QTxIqtlhTeLZ5C5k6XsWhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHhCeZ/btsIQEmJdqH/QTxIqtlhTeLZ5C5k6XsWhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHhCeZ%2FbtsIQEmJdqH%2FQTxIqtlhTeLZ5C5k6XsWhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;285&quot; height=&quot;183&quot; data-origin-width=&quot;285&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 사용자 영역에 추가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ Tip&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VsCode에서 code . 으로 실행하려는데 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ctrl + shift + p 로도 code 를 검색해서 찾는데 뭐 안뜬다&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;Vs Code 또한 Custom 영역에 설치해서 그럼.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 환경 변수에서 Vs Code 위치를 알려주면 됨.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;38&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ow2Gn/btsITaRO1mS/ATmSZ8XBRBXzd3WHDigC1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ow2Gn/btsITaRO1mS/ATmSZ8XBRBXzd3WHDigC1k/img.png&quot; data-alt=&quot;시스템 환경변수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ow2Gn/btsITaRO1mS/ATmSZ8XBRBXzd3WHDigC1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fow2Gn%2FbtsITaRO1mS%2FATmSZ8XBRBXzd3WHDigC1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;258&quot; height=&quot;38&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;38&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시스템 환경변수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고 bash에서 프로젝트 폴더로 이동한 뒤 code . 을 찍으면 잘된다.&lt;/p&gt;</description>
      <category>JavaScript/Vanila</category>
      <category>FRONT</category>
      <category>js</category>
      <category>node</category>
      <category>Node js</category>
      <category>react</category>
      <category>Visual Studio Code</category>
      <category>VS Code</category>
      <category>리액트</category>
      <category>프론트</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/88</guid>
      <comments>https://dev-dot.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0#entry88comment</comments>
      <pubDate>Tue, 30 Jul 2024 21:01:05 +0900</pubDate>
    </item>
    <item>
      <title>[실기 후기] 정보처리기사</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%ED%9B%84%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;가채점 결과 3문제가 틀렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 공부 시간은 블로그에 작성한 모의고사 끝이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전공자의 경우, 코딩만 준비가 되어있으면 하루만 공부해도 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WEj4W/btsIRmMDj0i/10oATRtam17NdkW5yX0cLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WEj4W/btsIRmMDj0i/10oATRtam17NdkW5yX0cLK/img.png&quot; data-alt=&quot;https://namu.wiki/w/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC/%EC%B6%9C%EC%A0%9C%EA%B2%BD%ED%96%A5&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WEj4W/btsIRmMDj0i/10oATRtam17NdkW5yX0cLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWEj4W%2FbtsIRmMDj0i%2F10oATRtam17NdkW5yX0cLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;407&quot; height=&quot;549&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://namu.wiki/w/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC/%EC%B6%9C%EC%A0%9C%EA%B2%BD%ED%96%A5&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 22년도부터 24년까지 모의고사를 풀어봤는데 개인적으로 23년 2회, 3회와 비슷한 합격률을 보이지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 코드가 상당히 어려울 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀를 이용한 메모제이션 기법이 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외 포인터가 다양하게 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이론&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크, 보안만 공부했으면 됐을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 회차에 비해 코딩 : 상, 이론 : 하&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 비전공자가 많이 응시했다면 합격률이 좀 낮을 것으로 예상된다.&lt;/p&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>정보처리기사</category>
      <category>정보처리기사 후기</category>
      <category>정처기 실기 후기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/87</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%ED%9B%84%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC#entry87comment</comments>
      <pubDate>Tue, 30 Jul 2024 19:34:32 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 22년 1회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-1%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;RAID에 대해 적은 것이 있따.&lt;/li&gt;
&lt;li&gt;RAID 0
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;스트라이핑 방식&lt;/li&gt;
&lt;li&gt;중복 저장이 안되므로 데이터가 유실될 수 있다.&lt;/li&gt;
&lt;li&gt;패리티가 없어서 에러검출이 안된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID 1
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;미러링 방식&lt;/li&gt;
&lt;li&gt;중복 저장이 된다.&lt;/li&gt;
&lt;li&gt;신뢰도가 높다. 다만 용량적인 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID 2
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;스트라이핑&amp;nbsp;&lt;/li&gt;
&lt;li&gt;RAID1에서 해밍코드로 에러검증&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID 3
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;스트라이핑&amp;nbsp;&lt;/li&gt;
&lt;li&gt;바이트 단위 패리티로 에러검증&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID 4
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;블록 단위&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID 5
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;패리티 블록을 각 디스크마다 분산 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID 6
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;패리티 블록을 이중구조로 구축&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;틀리라고 낸 문제 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;REDO
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DB가 비정상적 종료 시 디스크에 저장된 로그를 분석&lt;/li&gt;
&lt;li&gt;트랜잭션 시작과 완료의 기록이 있는 트랜잭션들의 작업을 재작업&lt;/li&gt;
&lt;li&gt;로그를 이용해 해당 데이터 항목에 대해 이전 값을 이후 값으로 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UNDO
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;commit 기록이 없는 트랜잭션들이 작업한 내용들을 모두 취소&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Atomicity(원자성)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;트랜잭션 연산은 DB에 모두 반영되도록 완료(commit) 되어야 함&lt;/li&gt;
&lt;li&gt;아니면 전혀 반영되지 않도록 복구 (Rollback) 되어야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Consistency (일관성)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 DB 상태로 변환함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Isolation (독립성)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;둘 이상의 트랜잭션이 동시에 병행 실행되는 경우&lt;/li&gt;
&lt;li&gt;트랜잭션이 실행중에 다른 트랜잭션의 연산이 끼어들 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DUrability (지속성)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;성공적으로 완료된 트랜잭션 결과는 영구적으로 반영되어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다이어그램
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사물과 관계를 도형으로 표현&lt;/li&gt;
&lt;li&gt;구조적 다이어그램 - 정적 모델링
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;클래스, 객체(럼바우 객체), 컴포넌트, 배치 다이어그램, 복합체 구조 다이어 그램, 패키지 다이어그램&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;행위 다이어그램 - 동적 모델링&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;유스케이스, 시퀀스, 커뮤니케이션, 상태(럼바우 동적), 활동, 상호작용, 타이밍&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;럼바우 기능 - DFD&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정보보호 관리 체계(ISMS: Information Security Management System)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정보 자산을 안전하게 보호하기 위한 보호 절차와 대책&lt;/li&gt;
&lt;li&gt;조직에 맞는 정보보호 정책을 수립&lt;/li&gt;
&lt;li&gt;위험에 상시 대응하는 여러 보안 대책을 통합해 관리&lt;/li&gt;
&lt;li&gt;KISA가 정보보호 관리 체계를 평가하고 인증하는 업무를 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그 외 정보보호 법? 너무 딥해서 패스&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알겠는데 애매한거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;단위 테스트 (Unit Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;최소 단위인 모듈이나 컴포넌트에 초점을 맞추어 테스트&lt;/li&gt;
&lt;li&gt;사용자의 요구사항을 기반으로 한 기능성 테스트를 최우선 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;통합 테스트 (Integration Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;단위 테스트가 완료된 모듈들을 결합&lt;/li&gt;
&lt;li&gt;하나의 시스템으로 완성시키는 과정에서의 테스트&lt;/li&gt;
&lt;li&gt;모듈 간 or 통합된 컴포넌트 간 상호 작용 오류 검사&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;시스템 테스트 (system Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SW가 시스템에서 완벽하게 수행되는가 점검하는 테스트&lt;/li&gt;
&lt;li&gt;기능적 요구사항과 비기능적 요구사항으로 구분&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인수 테스트 (Acceptance Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;개발한 SW가 사용자의 요구사항을 충족하는지 중점을 둑 ㅗ테스트&lt;/li&gt;
&lt;li&gt;사용자와 개발자가 직접 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;18번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;후보 키
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;후보키 중 main key&lt;/li&gt;
&lt;li&gt;중복된 값과 NULL을 가질 수 없음&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;후보키가 둘 이상일 때 기본키를 제외한 나머지 후보키&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;슈퍼키
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;유일성만 만족하고 최소성은 만족하지 못함&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다른 릴레이션의 기본키를 참조하는 속성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>It</category>
      <category>자격증</category>
      <category>정보처리기사</category>
      <category>정보처리기사 실기</category>
      <category>정보처리기사 필기</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/86</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-1%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8#entry86comment</comments>
      <pubDate>Sun, 28 Jul 2024 07:37:52 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 22년 2회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-2%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;관계대수
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;원하는 정보와 그 정보를 검색하기 위해 어떻게 유도하는가를 기술&lt;/li&gt;
&lt;li&gt;절차적인 언어, 릴레이션 처리&lt;/li&gt;
&lt;li&gt;연산자와 연산 규칙을 제공&lt;/li&gt;
&lt;li&gt;피연산자와 연산 결과가 모두 릴레이션&lt;/li&gt;
&lt;li&gt;해를 구하기 위한 연산의 순서를 명시&lt;/li&gt;
&lt;li&gt;순수 관계 연산자와 일반 집합 연산잦가 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;관계해석 (Relational Calculus)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;수학의 술어 해석(Predicate Calculus)에 기반을 두고 관계 데이터 베이스를 위해 제안&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;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;소프트웨어 개발 단계 -&amp;gt; 테스트 단계
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;요구사항 -&amp;gt; 분석 -&amp;gt; 설계 -&amp;gt; 구현 -&amp;gt;&lt;/li&gt;
&lt;li&gt;단위 테스트 -&amp;gt; 통합 테스트 -&amp;gt; 시스템 테스트 -&amp;gt; 인수 테스트&lt;/li&gt;
&lt;li&gt;시스템 테스트, 인수 테스트 잘 기억하기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인수테스트 (Acceptance Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자 인수 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자가 시스템 사용의 적절성 여부를 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;운영상의 인수 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시스템 관리자가 시스템 인수 시 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;계약 인수 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;계약상 인수/검수 조건을 준수하는지 여부 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;규정 인수 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정부 지침, 규정 등에 맞게 개발 되었는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;알파 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;개발자의 장소에서 사용자가 개발자 앞에서 행함.&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;선정된 최종 사용자 여러명의 사용자가 직접 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로그램 실행 여부에 따른 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정적 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로그램을 실행하지 않고 소스 코드를 대상으로 분석&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;동적 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로그램 실행 중 오류를 찾는 테스트&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;명세 기반 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자의 요구사항에 대한 명세를 빠짐 없이 테스트 케이스로 만듬&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;구조 기반 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SW 내부 논리 흐름에 따라 테스트 케이스 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;경험 기반 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;유사 SW, 기술 등 테스터의 경험을 기반으로 수행&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;검증(Verification) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;개발자의 시각에서 제품의 생산 과정을 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;확인 (Validation) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;회복(Recovery) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;여러가지 결함을 주어 실패 후, 복구 되는지 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;안전 (Security) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시스템 보호 도구가 불법적인 침입으로부터 보호할 수 있는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;강도(Stress) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시스템에 과도한 정보량이나 빈도 등을 부과&lt;/li&gt;
&lt;li&gt;과부하 시에도 SW가 정상적으로 되는지 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;성능 (Performance) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SW 실시간 성능이나 전체적인 효율성 진단&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;구조 (Structure) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SW 내부의 경로, 소스 코드의 복잡 평가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;회귀 (Regression) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;변경 또는 수정된 코드에 새로운 결함이 없는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;병행(Parallel) 테스트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;변경된 SW와 기존 SW에 동일한 데이터를 입력해 결과를 비교&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애매&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;where (다중 데이터) 절에서는 in, any, all이 있다.&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;6번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;단일 책임의 원칙 (SRP, Single Responsibility Principle)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;객체는 단 하나의 책임만 가져야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개방-폐쇠의 원칙 (OCP, Open-Closed Principle)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기존의 코드를 변경하지 않고 기능을 추가할 수 있도록 설계해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;리스코프 치환의 원칙(LSP, Liskov SUbsitution Principle)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자식 클래스는 최소한 부모 클래스의 기능은 수행할 수 있어야 한다는 원칙&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터페이스 분리의 원칙 (ISP, Inserface &lt;span style=&quot;background-color: #ffffff; color: #4d5156; text-align: left;&quot;&gt;Segregation&lt;/span&gt; Principle)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자신이 사용하지 않는 인터페이스와 의존 관계를 맺으면 안된다.&lt;/li&gt;
&lt;li&gt;영향도 받아서는 안된다.&lt;/li&gt;
&lt;li&gt;지 인터페이스는 지꺼만 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;의존 역전의 원칙 (Dependency Inversion Principle)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;의존 관계 성립시 추상성이 높은 클래스와 의존 관계를 맺어야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>오답노트</category>
      <category>정처기</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/85</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-2%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8#entry85comment</comments>
      <pubDate>Sun, 28 Jul 2024 05:28:49 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 23년 2회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-23%EB%85%84-2%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;8번 - 오답노트 먼저 안적고 테스트해서 틀림&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;23년 3회차 2번 보면 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;후진 오류 정정 (Backward Error Correction, BEC)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;수신측에서 송신측으로 오류가 났다고 알림&lt;/li&gt;
&lt;li&gt;역방향 채널을 통해 송신 측에 재전송을 요구&lt;/li&gt;
&lt;li&gt;Parity, CRC 등으로 오류 검출&lt;/li&gt;
&lt;li&gt;ARQ(자동 반복 요청)로 오류 정정
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Stop-wait, Continuous(Go-Back-N, SR), Adaptive(적응적)&lt;/li&gt;
&lt;li&gt;ack 응답과 nak 응답으로 긍정 부정 응답&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전진 오류 정정 (Forward Error Correction, FEC)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;수신측에서 송신측의 오류를 고침&lt;/li&gt;
&lt;li&gt;Hamming Code를 사용해서 오류 검출 후 수정&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 데이터 단위에 패리티 비트를 추가해 오류 검출&lt;/li&gt;
&lt;li&gt;2bit의 오류를 검출할 수 있고 1bit의 오류를 교정함.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애매한거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;13번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;HDLC
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;I-frame : figgybacking 함.&lt;/li&gt;
&lt;li&gt;표준 응답 모드 (NRM), 비동기 응답 모드 (ARM), 비동기 균형 모드 (ABM)이 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;암호 알고리즘
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;평문을 암호화된 문장으로 바꿈&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;양방향 암호화
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;개인키
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;동일한 키로 데이터를 암호화 및 복호화&amp;nbsp;&lt;/li&gt;
&lt;li&gt;대칭 암호 기법 또는 단일키 암호화 기법이라고도 함. (대칭 키)&lt;/li&gt;
&lt;li&gt;속도가 빠르지만 관리할 키가 많음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개인키 Stream
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;평문과 동일한 길이의 스트림을 생성해서 비트 단위로 암호화&lt;/li&gt;
&lt;li&gt;LFSR, RC4, TKIP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개인키 Block
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;한 번에 하나의 데이터 블록을 암호화 하는 방식&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;DES (Data Encryption Standard)&lt;/span&gt;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;64bit block, 키 길이 56bit, 16회의 라운드를 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DES를 3번 적용한 3DES(Triple DES)도 있음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AES
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DES의 한계를 느낌&lt;/li&gt;
&lt;li&gt;128 bit block, 길이에 따라 128,192,256으로 분류&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ARIA (Academy, Research Institute, Agency)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;국가 정보원 + 산합연혁회가 개발, 2004년 별로 안중요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SEED
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;128 bit block, 키 길이에 따라 128, 256 (별로 안중요한듯)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;IDEA
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;64bit block, 128 bit length&lt;/li&gt;
&lt;li&gt;PES라는 것을 개선한 알고리즘&lt;/li&gt;
&lt;li&gt;현재 가장 안전하고 최고&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Skipjack
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;64bit block, 80 bit length&lt;/li&gt;
&lt;li&gt;음성 데이터를 보완함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TKIP(Temporal Key Integrity Protocol)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;무선랜 보안에 사용된 WEP을 보완한 데이터 보안 프로토콜&lt;/li&gt;
&lt;li&gt;임시 키 무결성 프로토콜&lt;/li&gt;
&lt;li&gt;WEP의 취약성을 보완하기 위해 입력 키 길이를 128bit로 늘림&lt;/li&gt;
&lt;li&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;암호화시 사용자에게 공개하고 복호화 시 관리자가 관리하는 암호화 기법&lt;/li&gt;
&lt;li&gt;비대칭 암호화 기법 (비대칭키)&lt;/li&gt;
&lt;li&gt;관리할 키의 수는 적지만 암호화/복호화 속도가 느림&lt;/li&gt;
&lt;li&gt;RSA(Rivest Shamir Adleman)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;큰 숫자를 소인수분해 하기 어렵다는 것에 기반함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ECC (Elliptic Curve Cryptography)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&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;/li&gt;
&lt;li&gt;단방향 암호화
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;HASH
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;나중에 나옴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;17번&lt;/p&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;Create Schema schema_name authorizaition user_id;

CREATE DOMAIN SEX CHAR(1)
       DEFAULT 'M'
       CONSTRAINT VALD-SEX CHECK (VALUE IN('M'.'F'));
       
CREATE INDEX INDEX_NAME 
ON TABLE_NAME(COL1 ASC or DESC);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;RESTRICT: 다른 개체가 제거할 요소를 참조중일 때는 제거를 취소&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하향식은 하위 모듈에 접근하기 위해 스텁이 필요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상향식은 상위 모듈이 아직 없기 때문에 시험용 입출력하는 확인하는 인터페이스 드라이버가 필요함.&lt;/p&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>오답노트</category>
      <category>정처기</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/84</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-23%EB%85%84-2%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8#entry84comment</comments>
      <pubDate>Sun, 28 Jul 2024 04:49:12 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 23년 3회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-3%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8-1</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;22년 3회차 10번에 이어서 공부하면 좋음&lt;/li&gt;
&lt;li&gt;SSH (Secure Shell, 시큐어 셸)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다른 컴퓨터에 로그인, 원격 명령, 파일 복사등 다양한 기능을 지원하는 프로토콜&lt;/li&gt;
&lt;li&gt;데이터 암호화, 강력한 인증으로 보안성 낮은 네트워크에서도 통신 가능&lt;/li&gt;
&lt;li&gt;클라이언트의 공개키를 서버에 등록해야 함.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;키 인증 시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;22번 포트 사용
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;TCP 접속으로 함&lt;/li&gt;
&lt;li&gt;FTP : 21, TELNET : 23, SMTP : 25, DNS : 53, HTTP : 80&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;템퍼 프루핑 (Tamper Proofing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;소프트웨어 위, 변조가 발생 시 SW를 오작동하도록 만듦&lt;/li&gt;
&lt;li&gt;악용을 방지함, 해시 함수, 핑커 프린트, 워터마킹 등 보안 요소를 생성 후 SW에 삽입&lt;/li&gt;
&lt;li&gt;실행 코드 난독화, 실행 시 원본과 비교하거나 데이터를 확인하면서 SW 보호&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OAuth (Open Authorization, 공개 인증)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;공개 API로 구현된 표준 인증 방법&lt;/li&gt;
&lt;li&gt;비밀번호를 제공하지 않고 다른 웹 사이트 상의 자신들의 정보에 대해 접근 권한을 부여 할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;화이트박스 테스트 (White Box Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;원시 코드의 논리적인 모든 경로 테스트&lt;/li&gt;
&lt;li&gt;기초 경로 검사 (Base Path Testing)&lt;/li&gt;
&lt;li&gt;제어 구조 검사 (Control Structure Testing)&lt;/li&gt;
&lt;li&gt;검증 기준
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;24년 1회차 7번인가 9번에 적힘&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;블랙박스 테스트 (Black Box Test)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;각 기능이 완전히 작동되는 것을 입증하는 테스트&lt;/li&gt;
&lt;li&gt;동치 분할 검사(Equivalence Partitioning Testing, 동치 클래스 분해)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;입력 값이 타당한지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;경계값 분석 (Boundary Value Analysis)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;경계 값에서 오류가 발생할 확률이 높은 점을 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;원인-효과 그래프 검사 (Cause-Effect Graphing Testing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;입력이나 출력에 미치는 영향을 분석해서 테스트 케이스를 선정해서 검사&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;오류 예측 검사 (Error Guessing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;과거의 경험이나 감각으로 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;비교 검사(Comparison Testing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;동일한 테스트 케이스를 주고 동일한 결과를 반환하는&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;ATM (Asynchronous Transfer Mode, 비동기 전송 모드)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;교환 전화 등 회선 교환과 패킷 교환의 장점을 결합한 다중화 기술&lt;/li&gt;
&lt;li&gt;모든 데이터를 셀(Cell)로 분할해 비동기식 TDM으로 전송&lt;/li&gt;
&lt;li&gt;셀은 53Byte, 고정길이&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;17번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Iaas(Infrastructure as a Service)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;서버, 스토리지, 네트워크 등 HW InfraStructure를 가상화해서 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Paas(Platform as a Service)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;런타임, 미들웨어, OS 등 SW 작성을 위한 플랫폼을 가상화해서 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Saas(Software as a Service)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SW 여러 기능 중 사용자가 필요로 하는 기능을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전통적인 IT 기업의 관리 영역을 분할해서 전문적으로 가상화로 제공하는 서비스들이다.&lt;/li&gt;
&lt;li&gt;Iaas &amp;lt; Paas &amp;lt; Saas 순으로 제공하는 서비스가 많음. IPS&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 아는 것들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;UNION : 중복된 것 제거&lt;/li&gt;
&lt;li&gt;UNION ALL : 중복 포함&lt;/li&gt;
&lt;li&gt;INTERSECT : 교집합&lt;/li&gt;
&lt;li&gt;EXCEPT : 차집합&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;13번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;접근통제
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;임의접근통제(DAC, Discretionary Access Control)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터에 접근하는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;사용자의 신원에 따라 접근 권한&lt;/span&gt;&lt;/b&gt;을 부여&lt;/li&gt;
&lt;li&gt;데이터 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;소유자가 접근 통제 권한을 관리&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;객체를 생성한 사용자가 객체에 대해 모든 권한을 부여받음
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다른 사용자에게 권한 부여 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;강제 접근 통제 (MAC, Mandatory Access Control)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;등급&lt;/span&gt;&lt;/b&gt;으로 접근 권한을 부여&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;시스템이 접근 통제 권한&lt;/span&gt;&lt;/b&gt;을 지정&lt;/li&gt;
&lt;li&gt;DB 객체 별, 사용자 별로 보안 등급 부여 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;역할 기반 접근 통제 (RBAC, Role Based Access Control)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자의 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;역할에 따라&lt;/span&gt;&lt;/b&gt; 접근 권한을 부여&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;중앙 관리자가 권한&lt;/span&gt;&lt;/b&gt; 관리&lt;/li&gt;
&lt;li&gt;DAC와 MAC의 단점 보완&lt;/li&gt;
&lt;li&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Who가 When, Where, 어떤 객체(What)에게 어떤 것(How)에 대한 허용 여부를 정의&lt;/li&gt;
&lt;li&gt;신분 기반 정책
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;신분에 근거하여 객체의 접근 제한
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;IBP (Individual-Based Policy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;최소 권한 정책&lt;/li&gt;
&lt;li&gt;단일 주체에게 하나의 객체 대해 허가 부여&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GBP (Group-Based Policy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;복수 주체에게 하나의 객체에 대해 허가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MAC&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;주체가 갖는 권한에 근거해 접근 제한&lt;/li&gt;
&lt;li&gt;MLP (Multi-Level Policy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자나 객체 별로 분류&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CBP (Compartment-Based Policy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;집단 별로 기밀 허가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DAC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;역할 기반 정책
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;GBP의 변형된 정책&lt;/li&gt;
&lt;li&gt;신분뿐 아니라 역할에 근거해 접근 제한&lt;/li&gt;
&lt;li&gt;RBAC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;무결성 (Integrity)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DB의 저장된 값과 실제 값이 일치하는 정확성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;무결성 제약 조건
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터의 정확성을 보장하기 위해 부정확한 자료가 DB에 저장되는 것을 방지하는 제약조건&lt;/li&gt;
&lt;li&gt;&amp;nbsp;개체 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기본키는 Null 이나 중복을 못가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;참조 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;외래키는 Null 이거나 기본키와 동일해야 함.&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;속성 값이 도메인에 속한 값이어야 함. (범위 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용자 정의 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자가 정의한 제약 조건에 만족해야 함.&lt;/li&gt;
&lt;li&gt;NULL 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;특정 속성 값이 NULL이 될 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;고유 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;특정 속성 값은 서로 달라야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;키 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 키는 존재해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;관계 무결성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;연관 관계에 대한 적절성 여부를 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>정보처리기사</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/83</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-3%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8-1#entry83comment</comments>
      <pubDate>Sun, 28 Jul 2024 04:02:03 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 24년 1회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-24%EB%85%84-1%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;7번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;비정규형 -&amp;gt; 제 1정규형 (1NF)&amp;nbsp;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;모든 도메인이 원자값이어야 함.&lt;/li&gt;
&lt;li&gt;번호 : {a, b}, {c} 같은 꼴이 되면 안되고 번호 : {a}, {b}, {c} 와 같은 꼴이 되어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제 1정규형 -&amp;gt; 제 2정규형(2NF)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;1NF가 만족되어야 함.&lt;/li&gt;
&lt;li&gt;키가 아닌 모든 속성이 기본키 그룹에 완전하게 함수적 종속이 되어야 함.&lt;/li&gt;
&lt;li&gt;즉, 부분 종속성이 없어야 한다는 말임.&lt;/li&gt;
&lt;li&gt;기본키 = {고객아이디, 강좌명}, 종속되는 함수 -&amp;gt; 강사번호&lt;/li&gt;
&lt;li&gt;부분 집합 = {고객아이디}, {강좌명}&lt;/li&gt;
&lt;li&gt;고객아이디만으로 강사번호를 알 수 없음. -&amp;gt; 부분 종속성 없음.&lt;/li&gt;
&lt;li&gt;강좌명만으로 강사번호를 알 수 없음 -&amp;gt; 부분 종속성 알 수 없음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제 2정규형 -&amp;gt; 제 3정규형 (3NF)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;A -&amp;gt; B, B -&amp;gt; C, C -&amp;gt; A 뭐 이런게 없어야 한다.&lt;/li&gt;
&lt;li&gt;이 말은 기본키가 아닌 속성은 기본키에만 의존해야 한다는 말이다.&lt;/li&gt;
&lt;li&gt;기본키는 {고객아이디, 강좌명} 이고 비기본키는 {강사번호}뿐이므로 만족한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제 3정규형 -&amp;gt; BCNF (Boyce-Codd 정규형)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;모든 결정자가 후보키여야 한다.&lt;/li&gt;
&lt;li&gt;기본키이면서 후보키인 {고객아이디, 강좌명} 으로는 강사번호를 결정할 수 있다.&lt;/li&gt;
&lt;li&gt;추가로 강사번호로 어떤 강좌인지 결정할 수 있다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;강사번호는 후보키가 아니므로 분리하게 되면 BCNF를 만족한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;BCNF -&amp;gt; 제 4정규형 (4NF)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다치 종속성을 제거한다.&lt;/li&gt;
&lt;li&gt;기본키가 고객 아이디만 존재한다면, {고객아이디, 강좌명}과 {고객아이디, 강사번호}로 분리할 수 있다.&lt;/li&gt;
&lt;li&gt;최소 3개의 컬럼이 필요함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제 4정규형 -&amp;gt; 제 5정규형 (5NF)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;4NF에서 Join을 했을 경우, 1 : N 매핑이 되는 경우가 없어야 한다.&lt;/li&gt;
&lt;li&gt;즉, 조인 종속을 제거해야 된다는 것인데 더이상 분해가 안되어야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;BCNF를 잘하면 4NF랑 5NF도 잘됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LRU (Least Recently Used) : 가장 오랫동안 사용되지 않은 페이지 교체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LFU (Least Frequently Used) : 가장 적게 사용된 페이지 교체&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FIFO (First In First Out) : 먼저&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NUR (Not Used Recently) : 최근에 사용되지 않은 페이지, Clock 알고리즘&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;14번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;코드 커버리지&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;구문 커버리지 (State Coverage)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;모든 명령문을 한 번 수행하도록 하는 커버리지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결정 커비리지 (Decision Coverage) / 분기 커버리지 (Branch Coverage)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;전체 코드 내 조건을 결정하는 결과가 T 와 F가 한 번씩은 나와야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;조건 커버리지 (Condition Coverage)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;결정문 내에서 각 조건이 T 와 F가 한 번씩은 나와야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;조건/결정 커버리지 (Condition/Decision Coverage)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;조건 커버리지와 결정 커버리지의 최소한의 조합으로 전체 조건식이 T와 F가 나와야한다.&lt;/li&gt;
&lt;li&gt;개별 조건식 또한 T와 F가 한번씩 나와야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;변경 조건/결정 커버리지
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;개별 조건식이 다른 조건식에 영향을 받지 않음.&lt;/li&gt;
&lt;li&gt;전체 조건식의 결과에 영향을 줌&lt;/li&gt;
&lt;li&gt;T/T 일 때 T, T/F일 때 F, F/T 일 때 F라면, F/F 일 때 F라면, F/F는 측정하지 않음.&lt;/li&gt;
&lt;li&gt;F/F에서 T/F가 되든 F/T가 되든 F니까 반대로 다른 것들은 조건을 바꾸면 전체 결과가 바뀜&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다중 조건 커버리지 (Multiple Condition Coverage)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;모든 가능성이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;23년 1회차 8번 문제와 같이 공부하면 좋음&lt;/li&gt;
&lt;li&gt;Rootkit
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;불법적인 해킹에 사용되는 기능들을 제공하는 프로그램들의 모음&lt;/li&gt;
&lt;li&gt;권한이 없는 사용자가 접근할 수 없는 영역에 접근해서 시스템을 제어하도록 설계 됨.&lt;/li&gt;
&lt;li&gt;한우툴과 같은 해킹툴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Spyware
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자 동의 없이 설치되어 사용자 정보를 수집하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Remote Administration Tool
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;관리자가 네트워크를 통해 원격으로 시스템을 제어함.&lt;/li&gt;
&lt;li&gt;한우툴에 있음 강제 원격&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Evil Twin Attack
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;악성 쌍둥이 공격&lt;/li&gt;
&lt;li&gt;합법적인 Wifi와 유사한 네트워크를 설정해 사용자가 연결하도록 유도&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Logic Bomb
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;특정 조건이 충족되면 악성 코드를 실행하도록 함.&lt;/li&gt;
&lt;li&gt;날짜나 시간 등의 이벤트가 발생될 때 활성화 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오답은 아니지만 대충 아는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;응집도 - &lt;span style=&quot;color: #000000;&quot;&gt;기&lt;/span&gt;능적 &amp;gt; &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;순&lt;/span&gt;&lt;/b&gt;차적 &amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;교&lt;/span&gt;환적 &amp;gt; &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;절&lt;/span&gt;&lt;/b&gt;차적 &amp;gt; 시간적 &amp;gt; 논리적 &amp;gt; 우연적
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;우연적으로 쓰는건 당연히 꼴지일듯&lt;/li&gt;
&lt;li&gt;기능적은 당연히 제일 중요할듯&lt;/li&gt;
&lt;li&gt;순교절만 외우면 시간 &amp;gt; 논리라고 알 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;세타 조인 (Theta Join)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;조건을 만족하는 경우만 join on 이 만족&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;동등 조인(Equal Join)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;join on A = B 인경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자연 조인 (Natural Join)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;natural join, on이 없음. 그냥 동등 조인 중 중복되는건 없앰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;외부 조인 (Outer Join)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터 값이 존재하지 않더라도 필드가 추가되어서 모두 포함한 결과를 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;세미 조인 (Semi Join)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자연 조인 후, 한쪽 릴레이션의 튜플만 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그 외에도 크로스 조인, 내부 조인 등 있&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>시나공</category>
      <category>오답</category>
      <category>오답노트</category>
      <category>정보처리기사</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/82</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-24%EB%85%84-1%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8#entry82comment</comments>
      <pubDate>Sun, 28 Jul 2024 03:13:06 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 22년 3회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-3%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;5번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;FLSM (Fixed Length Subnet Mask)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Subnet Mask가 모든 서브넷에서 동일한 길이를 가지도록 네트워크를 나눈다.&lt;/li&gt;
&lt;li&gt;예를 들어 192.168.1.0/24 일 경우 상위 24bit는 사용하지 못한다.&lt;/li&gt;
&lt;li&gt;서브넷은 192.168.1.0 ~ 192.168.1.255 로 총 256개가 존재한다.&lt;/li&gt;
&lt;li&gt;3개의 서브넷으로 나눈다면 가장 가까운 2^n 을 찾는다. - 2^2 = 4&lt;/li&gt;
&lt;li&gt;4개의 서브넷으로 나누고 그 중 3개만을 사용한다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;192.168.1.0 ~ 192.168.1.63 (네트워크 0, 브로드캐스트 63)&lt;/li&gt;
&lt;li&gt;192.168.1.64 ~ 192.168.1.127 (네트워크 64, 브로드 캐스트 127)&lt;/li&gt;
&lt;li&gt;192.168.1.128 ~ 192.168.1.191 (네트워크 128, 브로드캐스트 191)&lt;/li&gt;
&lt;li&gt;192.168.1.192 ~ 192.168.1.255 (네트워크 192, 브로드 캐스트 255) - 얘는 사용 안됨&lt;/li&gt;
&lt;li&gt;각 64개씩 서브넷을 사용하므로 IP/26 으로 표현한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VLSM (Variable Length Subnet Mask)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;가변 길이로 서브넷을 나눈다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;각 서브넷에 50개, 30개, 20개의 호스트를 둔다고 가정&lt;/li&gt;
&lt;li&gt;1번 서브넷
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;호스트 + 네트워크 + 브로드 캐스트 = 52개 필요&lt;/li&gt;
&lt;li&gt;2^n 중 52에 가장 가까운 n을 찾음. 2^6 = 64&lt;/li&gt;
&lt;li&gt;192.168.1.0 ~ 192.168.1.63 (네트워크 0, 브로드캐스트 63)&lt;/li&gt;
&lt;li&gt;64개를 사용하므로 subnet mask은 26 -&amp;gt; 192.168.1.0/26&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2번 서브넷
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;32개 필요, 2^5&lt;/li&gt;
&lt;li&gt;192.168.1.64 ~ 192.168.1.95 (네트워크 0, 브로드 캐스트 95)&lt;/li&gt;
&lt;li&gt;32개를 사용하므로 subnet mask는 27 -&amp;gt; 192.168.1.64/27&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;3번 서브넷
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;22개 필요, 2^5&lt;/li&gt;
&lt;li&gt;192.168.1.96 ~ 192.168.1.127 (네트워크 96, 브로드 캐스트 127)&lt;/li&gt;
&lt;li&gt;32개를 사용하므로 subnet mask는 27 -&amp;gt; 192.168.1.64/27&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8번&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사회 공학 (Social Engineering)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;컴퓨터 보안 중 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인간 상호 작용&lt;/b&gt;&lt;/span&gt;의 깊은 신뢰를 바탕으로 사람들을 속이는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;정상 보안 절차를 깨트리기 위한&lt;/span&gt;&lt;/b&gt; 비기술적 시스템 침입 수단&lt;/li&gt;
&lt;li&gt;스피어 피싱 (Spear Phishing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사회 공학의 한 기법&lt;/li&gt;
&lt;li&gt;특정 대상을 선정 후 그 대상에게 일반적인 이메일로 위장한 메일을 지속적으로 발송&lt;/li&gt;
&lt;li&gt;메일의 본문 링크나 첨부된 파일을 클릭하도록 유도해 개인 정보 탈취&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다크 데이터 (Dark Datae)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;특정 목적을 가지고 데이터를 수집&lt;/li&gt;
&lt;li&gt;이후 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;활용되지 않고 저장만 되어있는 대량의 데이터&lt;/b&gt;&lt;/span&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;세션 하이재킹 (Session Hijacking)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;서버와 클라이언트 사이의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;세션 정보를 가로채는 공격&lt;/b&gt;&lt;/span&gt; 기법&lt;/li&gt;
&lt;li&gt;인증 정보 없이도 가로챈 세션 정보로 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;클라이언트처럼 위장&lt;/span&gt;&lt;/b&gt;해 서버에 접근&lt;/li&gt;
&lt;li&gt;서버의 자원이나 데이터를 무단으로 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;TCP 3-Way-Handshake 과정에 끼어들어&lt;/span&gt;&lt;/b&gt; 클라이언트와 서버 간 동기화된 시퀀스 번호를 가로챔
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;TCP 세션 하이재킹&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ARP Spoofing
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ARP의 취약점을 이용한 공격 기법&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;자신의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;물리적 주소 (MAC)을 공격대상의 것으로 변조&lt;/b&gt;&lt;/span&gt;함&lt;/li&gt;
&lt;li&gt;공격 대상에게 도달해야하는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;데이터 패킷을 가로채거나 방해&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스미싱 (Smishing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SMS를 이용해 개인 신용 정보를 빼냄&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;타이포스쿼팅 (Typosquatting)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네티즌들이 사이트 접속 시 주소를 잘못 입력하거나 철자를 빠뜨리는 실수를 이용&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;타이핑을 잘못하는 실수를 이용한다는 말&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;naver면 naber 같은 도메인을 미리 등록함&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;URL 하이재킹 (Hijacking)&lt;/b&gt;&lt;/span&gt; 이라고도 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;APT (Advanced Persistent Threats, 지능형 지속 위협)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다양한 IT 기술과 방식들을 이용해 조직적&lt;/b&gt;&lt;/span&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;무작위 대입 공격 (Brute Force Attack)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;암호화된 문서의 암호키를 찾아내기 위해 가능한 모든 값을 대입하여 공격&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;큐싱(Qshing)&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;QR코드&lt;/b&gt;&lt;/span&gt;를 통해 악성 앱의 다운로드를 유도, 악성 프로그램 설치하도록 하는 금융사기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SQL 삽입 (Injection) 공격
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;전문 스캐너 프로그램 혹은 봇넷&lt;/span&gt;&lt;/b&gt; 등을 이용해 웹사이트를 무차별적으로 공격&lt;/li&gt;
&lt;li&gt;취약한 사이트가 발견되면 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;DB 등의 데이터를 조작&lt;/span&gt;&lt;/b&gt;하는 공격방식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;크로스 사이트 스크립팅 (XSS: Cross Site Scripting)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네트워크를 통한 보안 공격&lt;/li&gt;
&lt;li&gt;웹 페이지 내용을 사용자 브라우저에 표현하기 위해 사용되는&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 스크립트의 취약점&lt;/b&gt;&lt;/span&gt;을 악용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스니핑 (Sniffing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네트워크의 중간에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;남의 패킷 정보를 도청&lt;/b&gt;&lt;/span&gt;하는 해킹 유형&lt;/li&gt;
&lt;li&gt;수동적 공격&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SIEM (Security Information &amp;amp; Event Management)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SIM (Security Information Management) + SEM(security Event Management)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다양한 장비에서 발생하는 로그 및 보안 이벤트를 통합하여 관리하는 보안 솔루션&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;방화벽, IDS, IPS, 웹 방화벽, VPN 등에서 발생한 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;로그 및 보안 이벤트를 통합하여 관리&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;보안 솔루션간 상호 연동을 통해 종합적인 보안 관리 체계를 수립 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ESM (Enterprise Security Management)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SIEM과 기능은 동일하지만, 짧은 기간동안만 관리함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;방화벽 (Firewall)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기업이나 조직 내부의 네트워크와 인터넷 간 전송되는 정보를 선별&lt;/li&gt;
&lt;li&gt;선별된 정보를 수용, 거부, 수정하는 기능을 가진 침입 차단 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;침입 탐지 시스템 (IDS: Intrusion Detection System)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;컴퓨터 시스템의 비정상적인 사용, 오용, 남용 등을 실시간으로 탐지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;침입 방지 시스템 (IPS: Instrusion Prevention System)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;비정상적인 트래픽을 능동적으로 차단하고 격리하는 등&lt;/li&gt;
&lt;li&gt;방어 조치를 취하는 보안 솔루션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터 유출 방지 (DLP: Daata Leakage/Loss Prevention)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;내부 정보의 외부 유출을 방지하는 보안 솔루션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;웹 방화벽 (Web Firewall)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;일반 방화벽이 탐지 못하는 SQL 삽입 공격, XSS 등 웹 기반 공격을 방어함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VPN (Virtual Private Network, 가상 사설 통신망)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;공중 네트워크와 암호화 기술을 이용해 자신의 전용 회선을 사용하는 것처럼 보이도록 해주는 보안 솔루션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NAC (Network Access Control)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네트워크에 접속하는 내부 PC의 MAC 주소를 Ip 관리 시스템에 등록&lt;/li&gt;
&lt;li&gt;일관된 보안 관리 기능을 제공하는 보안 솔루션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;14번, 8번과 이어서 공부&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;고가용성 (HA: High Availability)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;긴 시간동안 안정적인 서비스 운영을 위함.&lt;/li&gt;
&lt;li&gt;장애 발생 시 즉시 다른 시스템으로 대체 가능한 환경을 구축하는 매커니즘&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;3D Printing(Three Dimenstion Printing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;대상을 평면에 출력하는 것이 아님&lt;/li&gt;
&lt;li&gt;손으로 만질 수 있는 실제 물체로 만들어 냄.&lt;/li&gt;
&lt;li&gt;아주 얇은 두께로 한층한층 쌓아 하나의 형태를 만들어내는 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4D printing(Fourth Dimension Priting)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;특정 시간이나 환경 조건이 갖춰지면 스스로 형태를 변화시키거나 제조 됨&lt;/li&gt;
&lt;li&gt;자가조립(Self-Assembly) 기술이 적용된 제품을 3D Printing 하는 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAID (Redundant Array of Independent Disks)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;여러 개의 하드디스크로 디스크 배열을 구성&lt;/li&gt;
&lt;li&gt;파일을 구성하고 있는 데이터 블록들을 서로 다른 디스크들에 분산 저장할 경우, 여러 디스크에서 동시에 읽거나 쓸 수 있으므로 디스크 속도가 매우 향상 되는 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4K 해상도
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;차세대 고화질 모니터의 해상도&lt;/li&gt;
&lt;li&gt;가로 픽셀 수 3840, 세로 2160인 영상의 해상도&lt;/li&gt;
&lt;li&gt;Full HDTV = 1920x1080&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;앤 스크린 (N-Screen)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;N개의 서로 다른 단말기에서 동일한 콘텐츠를 자유롭게 이용할 수 있는 서비스&lt;/li&gt;
&lt;li&gt;컴패니언 스크린 (Companion Screen)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;TV 방송 시청 시 방송 내용을 공유하며 추가적인 기능을 수행할 수 있음&lt;/li&gt;
&lt;li&gt;앤 스크린의 한 종류, 세컨드 스크린(Second Screen)이라고도 불림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;신 클라이언트 PC (Thin Client PC)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하드디스크나 주변 장치 없이 메모리만 갖추고 서버와 네트워크로 운용되는 개인용 컴퓨터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;패블릿 (Phablet)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;폰과 태블릿의 합성어, 태블릿 기능을 포함한 5인치 이상의 대화면 스마트폰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;멤스 (MEMS: Micro-Electro Mechanical Systems)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;초정밀 반도체 제조 기술을 바탕으로 센서, 액추에이터 등 기계 구조를 다양한 기술로 미세 가공&lt;/li&gt;
&lt;li&gt;전기기계적 동작을 할 수 있도록 한 초 미세 장치&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;트러스트존 기술 (TrustZone Technology)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 프로세서 내에 일반 어플리케이션을 처리하는 일반 구역&lt;/li&gt;
&lt;li&gt;보안이 필요한 어플리케이션을 처리하는 보안 구역&lt;/li&gt;
&lt;li&gt;구역을 분리해 관리하는 하드웨어 기반 보안 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;엠 디스크(M-disc, Millennial Disc)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;한 번의 기록만으로 자료를 영구 보관할 수 있는 광 저장장치&lt;/li&gt;
&lt;li&gt;디스크 표면의 무기물층에 레이저를 이용해 자료를 조각해서 기록함.&lt;/li&gt;
&lt;li&gt;금속활자처럼 외부 요인을 받지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;멤리스터 (Memristor)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;메모리와 레지스터의 합성어&lt;/li&gt;
&lt;li&gt;전류의 방향, 양 등 기존의 경험을 모두 기억하는 특별한 소자&lt;/li&gt;
&lt;li&gt;레지스터, 커패시터, 인덕터에 이어 네번 째 전자회로 구성요소&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;IOT (Internet Of Things, 사물 인터넷)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정보 통신 기술을 기반으로 실세계와 가상 세계의 다양한 사물들을 인터넷으로 서로 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;M2M (Machine to Machine, 사물 통신)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;무선 통신을 이용한 기계와 기계 사이의 통신&lt;/li&gt;
&lt;li&gt;무선으로 통합하여 상호 작용하는 통신&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모바일 컴퓨팅 (Mobile Computing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;휴대형 기기로 이동하면서 자유로이 네트워크에 접속해 업무를 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클라우드 컴퓨팅 (Cloud Computing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;각종 컴퓨팅 자원을 중앙 컴퓨터에 두고 인터넷 기능을 갖는 단말기&lt;/li&gt;
&lt;li&gt;언제 어디서나 인터넷을 통해 컴퓨터 작업을 수행할 수 있는 가상화된 환경&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그리드 컴퓨팅 (Grid Computing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;지리적으로 분산되어 있는 컴퓨터를 초고속 인터넷 망으로 연결하여 공유&lt;/li&gt;
&lt;li&gt;하나의 고성능 컴퓨터처럼 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모바일 클라우드 컴퓨팅 (MCC: Mobile Cloud Computing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;소비자와 소비자의 파트너가 클라우드 서비스를 이용&lt;/li&gt;
&lt;li&gt;모바일 기기로 클라우드 컴퓨팅 인프라를 구성&lt;/li&gt;
&lt;li&gt;여러가지 정보와 자원을 공유하는 ICT 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터 클라우드 컴퓨팅 (Inter-Cloud Computing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;각기 다른 클라우드 서비스를 연동&lt;/li&gt;
&lt;li&gt;컴퓨팅 자원의 동적 할당이 가능&lt;/li&gt;
&lt;li&gt;여러 클라우드 서비스나 자원을 연결하는 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메시 네트워크 (Mesh Network)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;홈네트워킹, 공공안전 등 특수 목적을 위한 새로운 방식의 네트워크 기술&lt;/li&gt;
&lt;li&gt;대규모 디바이스의 네트워크 생성에 최적화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;와이선 (Wi-SUN)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;장거리 무선 통신을 필요로 하는 IoT 서비스를 위한 저전력 장거리 통신 기술&lt;/li&gt;
&lt;li&gt;저전력 장거리 (LPWA: Low-Power Wide Area)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NDN (Named Data Networking)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;콘텐츠 자체의 정보와 라우터 기능만으로 데이터 전송을 수행하는 기술&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NGN (Next Generation Network, 차세대 통신망)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;유선망 기반의 차세대 통신망&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SDN (Software Defined Networking, 소프트웨어 정의 네트워킹)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네트워크를 컴퓨터처럼 모델링&lt;/li&gt;
&lt;li&gt;여러 사용자가 각각의 소프트웨어로 네트워킹을 가상화하여 제어하고 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NFC (Near Field Communication, 근거리 무선 통신)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;고주파 (HF)를 이용한 근거리 무선 통신 기술&lt;/li&gt;
&lt;li&gt;아주 가까운 거리에서 양방향 통신을 지원하는 RFID 기술의 일종&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UWB (Ultra WideBand, 초광대역)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;짧은 거리에서 많은 양의 디지털 데이터를 낮은 전력으로 전송&lt;/li&gt;
&lt;li&gt;무선기술, 무선 디지털 펄스라고도 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;피코넷 (PICONET)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;독립된 통신장치가 블루투스 기술이나 UWB 통신 기술을 사용해 통신망을 형성하는 무선 네트워크 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;WBAN (Wireless Body Area Network)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;웨어러블 또는 몸에 심는 형태의 센서나 기기를 무선으로 연결&lt;/li&gt;
&lt;li&gt;개인 영역 네트워크 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GIS (Geographic Information System, 지리 정보 시스템)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;위성을 이용해 모든 사물의 위치 정보를 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;USN (Ubiquitous Sensor Network)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;각종 센서로 수집한 정보를 무선으로 수집할 수 있도록 구성한 네트워크&lt;/li&gt;
&lt;li&gt;필요한 모든 것에 RFID 태그를 부착&lt;/li&gt;
&lt;li&gt;사물의 인식정보, 주변의 환경 정보까지 탐지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SON (Self Organizing Network, 자동 구성 네트워크)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&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;애드 혹 네트워크 (Ad-hoc Network)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;고정된 유선망을 구축할 수 없는 장소에서 모바일 호스트만을 이용해 구성한 네트워크&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;네트워크 슬라이싱 (Network Slicing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네트워크에서 하나의 물리적인 코어 네트워크 인프라를 독립된 다수의 가상 네트워크로 분리&lt;/li&gt;
&lt;li&gt;각 각의 네트워크를 통해 다양한 고객 맞춤형 서비스를 제공하는 것이 목적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;저전력 블루투스 기술 (BLE: Bluetooth Low Energy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;2.4GHz 주파수 대역을 사용&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;스마트 시티, 스마트 스테이션 등 4차 산업혁명 시대에 변화가 급격함&lt;/li&gt;
&lt;li&gt;급격하게 증가하는 데이터 트래픽을 효과적으로 수용하기 위한 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;파장 분할 다중화 (WDM, Wavelength Division Multiplexing)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;광섬유를 이용한 통신 기술&lt;/li&gt;
&lt;li&gt;파장이 서로 다른 복수 신호를 보냄&lt;/li&gt;
&lt;li&gt;여러 단말기가 동시에 통신 회선을 사용할 수 있도록 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소프트웨어 정의 데이터 센터 (SDDC, Software Defined Data Center)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터 센터의 모든 자원을 가상화해서 인력의 개입없음&lt;/li&gt;
&lt;li&gt;소프트웨어 조작만으로 제어되는 데이터 센터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개방형 링크드 데이터 (LOD, Linked Open Data)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Linked Data와 Open Data의 합성어&lt;/li&gt;
&lt;li&gt;누구나 사용할 수 있도록 웹상에 공개된 연계 데이터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SSO(single Sign On)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;한번의 로그인으로 개인이 가입한 모든 사이트를 이용할 수 있게 해주는 시스템&lt;/li&gt;
&lt;li&gt;개인 정보를 각 사이트마다 기록하던 불편함을 해소&lt;/li&gt;
&lt;li&gt;기업에서는 회원 정보를 통합관리 함으로 마케팅 극대화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;FCFS (First Come First Service)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;준비상태 큐에 도착한 순서에 따라 차례로 CPU를 할당&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HRN (Highest Reponse-ratio Next)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;대기 시간과 서비스 시간을 이용하는 기법&lt;/li&gt;
&lt;li&gt;실행 시간이 긴 프로세스에 불리한 SJF 기법을 보완&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SJF (Shortest Job First)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;대기 큐에서 기다리고 있는 프로세스 중 실행 시간이 가장 짧은 프로세스에게 CPU를 할당&lt;/li&gt;
&lt;li&gt;가장 적은 평균 대기시간을 제공하는 최적 알고리즘&lt;/li&gt;
&lt;li&gt;실행 시간이 짧은 프로세스 때문에 긴 프로세스는 무한 연기가 될 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RR (Round Robin)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시분할 시스템을 위해 고안된 방식&lt;/li&gt;
&lt;li&gt;준비상태 큐에 먼저 들어온 프로세스가 먼저 CPU를 할당 받음&lt;/li&gt;
&lt;li&gt;시간 할당량 동안만 실행&lt;/li&gt;
&lt;li&gt;실행이 완료되지 않으면 다음 프로세스에게 CPU를 넘겨주고 대기 큐의 마지막으로&lt;/li&gt;
&lt;li&gt;타임 슬라이스가 작을 경우, 컨텍스트 스위칭, 오버헤드가 자주 발생해서 성능 저하&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SRT (Shortest Remaining Time)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;현쟁 실행중인 프로세스의 남은 시간과 대기 큐에 새로 도착한 프로세스의 시간을 비교&lt;/li&gt;
&lt;li&gt;실행 시간이 짧은 프로세스에게 CPU 할당, 시분할 시스템에 유용&lt;/li&gt;
&lt;li&gt;준비 상태 큐에 있는 각 프로세스의 실행 시간을 추적하고 보유하고 있어야 함 -&amp;gt; 성능 저하&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>2023년 3회 정보처리기사</category>
      <category>22년 3회</category>
      <category>시나공</category>
      <category>시나공 정보처리기사</category>
      <category>정보처리기사</category>
      <category>정보처리기사 실기</category>
      <category>정보처리기사 필기</category>
      <category>정처기</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/81</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-22%EB%85%84-3%ED%9A%8C-%EA%B8%B0%EC%B6%9C-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8#entry81comment</comments>
      <pubDate>Fri, 26 Jul 2024 17:58:29 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 정보처리기사 23년 1회 기출 오답노트</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-23%EB%85%84-1%ED%9A%8C-%EA%B8%B0%EC%B6%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;4번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터페이스 구현&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;송, 수신 시스템 간 데이터 교환 및 처리를 실현해주는 작업&lt;/li&gt;
&lt;li&gt;데이터 통신을 이용한 구현 - AJAX, Http2, Rest, ...&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Application 영역&lt;/span&gt;&lt;/b&gt;에서 data format을 인터페이스 대상으로 전송&lt;/li&gt;
&lt;li&gt;수신측에서 파싱하여 해석&lt;/li&gt;
&lt;li&gt;JSON, XML 형식의 데이터 포맷이 있음.&lt;/li&gt;
&lt;li&gt;JSON을 이용한 인터페이스 구현 순서
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;송신 측
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;생성할 데이터를 각 시스템 환경에 맞게 인터페이스 객체를 선택&lt;/li&gt;
&lt;li&gt;JSON을 이용해 데이터를 인터페이스 객체로 만듦&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터페이스 객체를 수신&lt;/li&gt;
&lt;li&gt;파싱 후 처리&lt;/li&gt;
&lt;li&gt;송신 측으로 처리 결과 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AJAX (Asynchronous Javascript and XML)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;js 를 사용해 클라이언트와 서버 간 XML 데이터를 주고 받는 '&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;비동기 통신&lt;/span&gt;&lt;/b&gt;' 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;JSON (JavaScript Object Notation)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;용량이 적은 데이터를 교환하기 위한 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;데이터의 쌍&lt;/span&gt;&lt;/b&gt;(Attribute-Value Pairs) 형태로 표현하는 개방형 표준 포맷&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;XML을 대체&lt;/span&gt;&lt;/b&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;span style=&quot;color: #333333; text-align: left;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;API Docs (Swagger)&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터페이스가 필요한 시스템 사이 별도의 인터페이스 엔티티를 두어 상호연계&lt;/li&gt;
&lt;li&gt;일반적으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스 테이블&lt;/b&gt;&lt;/span&gt;을 엔티티로 활용&amp;nbsp;&lt;/li&gt;
&lt;li&gt;인터페이스 테이블을 이용한 인터페이스 구현 순서
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;송신 측
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&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: circle;&quot; data-ke-list-type=&quot;circle&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;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;VPN (Virtual Private Network, 가상 사설 통신망)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터넷 등 통신 사업자(ISP)의 공중 네트워크와 암호화 기술을 이용&lt;/li&gt;
&lt;li&gt;사용자가 마치 전용 회선을 사용하는 것처럼 해주는 보안 솔루션&lt;/li&gt;
&lt;li&gt;SSL VPN
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;PC에 VPN Client 프로그램을 설치하여 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;VPN 서버에 접속&lt;/span&gt;&lt;/b&gt;하는 방식&lt;/li&gt;
&lt;li&gt;암호화를 위해 SSL 프로토콜을 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;IPSec VPN
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;VPN 서버가 설치된 각 네트워크를 서로 연결&lt;/span&gt;&lt;/b&gt;하는 방식&lt;/li&gt;
&lt;li&gt;암호화를 위해 IPSec 프로토콜을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SSL(Secure Sockets Layer)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;송, 수신 하는 컴퓨터 사이 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;TCP/IP 계층과 애플리케이션 계층 사이&lt;/span&gt;&lt;/b&gt;에서 인증, 암호화, 무결성을 보장하는 표준 프로토콜&lt;/li&gt;
&lt;li&gt;즉, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;전송 계층과 어플리케이션 계층&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;IPsec(IP security)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;네트워크 계층&lt;/span&gt;&lt;/b&gt;에서 IP 패킷 단위의 데이터 변조 방지 및 은닉 기능을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PPTP(Point-to-Point Tunneling Protocol)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;지점 간 터널링&lt;/span&gt;&lt;/b&gt; 프로토콜&lt;/li&gt;
&lt;li&gt;MS가 제안한 VPN 프로토콜&lt;/li&gt;
&lt;li&gt;PPP에 기초, 두 대가 직렬 인터페이스를 이용해 통신&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;데이터 링크 계층&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;L2F(Layer 2 Forwarding)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Cisco Systems가 개발한 VPN 프로토콜&lt;/li&gt;
&lt;li&gt;PPTP나 IPsec과 달리, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;데이터 링크 수준에서 캡슐화&lt;/span&gt;&lt;/b&gt;가 가능&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;IP 네트워크 이외에서도 사용 가능&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;L2TP (Layer 2 Tunneling Protocol)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;터널링 프로토콜인 PPTP와 VPN 구현에 사용&lt;/li&gt;
&lt;li&gt;L2F의 기술적 장점을 결합&lt;/li&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;워터링 홀 (Watering Hole)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;목표 조직이 자주 방문하는&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 웹 사이트를 사전에 감염&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;목표 조직이 웹 사이트에 방문했을 때, 악성 코드에 감염되게 하는 웹 기반 공격&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;웜 (Worm)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;네트워크를 통해 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;연속적으로 자신을 복제&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;시스템 부하를 높여 시스템을 다운&lt;/span&gt;&lt;/b&gt; 시킴&lt;/li&gt;
&lt;li&gt;분산 서비스 공격 (Dos), 버퍼 오버플로 공격, 슬래머 등으로 진화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;좀비(Zombie) PC
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;악성코드에 감염되어 다른 프로그램이나 컴퓨터를 조종함.&lt;/li&gt;
&lt;li&gt;C&amp;amp;C (Command &amp;amp; Control) 서버의 제어를 받아 Ddos 공격 등에 이용되는 PC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;C&amp;amp;C 서버
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;해커가 원격지에서 감염된 좀비 PC에 명령을 내림&lt;/li&gt;
&lt;li&gt;악성코드를 제어하는 용도로 사용 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;봇넷 (Botnet)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;악성 프로그램에 감염되어 악의적인 의도로 사용될 수 있는 다수의 PC가 네트워크로 연결된 형태&lt;/li&gt;
&lt;li&gt;즉, 좀비 PC의 네트워크(?)&lt;/li&gt;
&lt;li&gt;공격자는 Master 시스템(좀비 PC)으로 Agent 시스템(좀비 PC)를 조종해 공격대상에 분산 공격을 하든 할 수 있음&lt;/li&gt;
&lt;li&gt;Master 시스템 역할을 핸들러(Handler)라고 하고 Agent 시스템 역할을 데몬(Demon)이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제로 데이 공격 (Zero Day Attack)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;보안 취약점이 발견 되었을 때, 발견된 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;취약점이 공표되기 전&lt;/span&gt;&lt;/b&gt; 공격&lt;/li&gt;
&lt;li&gt;취약점을 통해 이루어지는 보안 공격, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;신속하게 해야 하므로 제로데이&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;nbsp;키로거 공격 (Key Logger AttacK)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;컴퓨터 사용자의 키보드 움직임을 탐지해 중요한 정보를 빼감&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;랜섬 웨어 (Ransomeware)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터넷 사용자 PC에 잠입, 내부 문서나 파일 등을 암호화 함.&lt;/li&gt;
&lt;li&gt;암호 해독용 프로그램을 조건으로 돈을 요구 하는 악질&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;백도어 (Back Door, Trap Door)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시스템 설계자가 서비스 기술자, 유지 보수 프로그래머 등의 접근 용이성을 위해 만들어 놓은 비밀 통로&lt;/li&gt;
&lt;li&gt;해커가 시스템 보안이 제거된 비밀 통로를 찾아서 컴퓨터 범죄에 악용함&lt;/li&gt;
&lt;li&gt;무결성 검사, 열린 포트, 로그 분석, setUID 파일 검사 등으로 백도어 탐지 가능&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;트로이 목마 (Trojan Horse)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정상적인 기능을 하는 프로그램으로 위장해 프로그램 내 숨어 있음&lt;/li&gt;
&lt;li&gt;프로그램이 동작할 때, 활성화되어 부작용을 일으킴&lt;/li&gt;
&lt;li&gt;좀비 PC로 만들 때, 악성 프로그램을 정상 프로그램과 합성해서 배포&lt;/li&gt;
&lt;li&gt;정상 프로그램 실행 시 좀비 PC가 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11번&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;디자인 패턴
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;모듈 간 관계 및 인터페이스 설계 시 참조할 수 있는 전형적인 방식 또는 예제&lt;/li&gt;
&lt;li&gt;GoF의 디자인 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;생성 패턴 (Creational Pattern)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;클래스나 객체의 생성과 참조 과정을 정의&lt;/li&gt;
&lt;li&gt;추상 팩토리 (Abstract Factory)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;구체적인 클래스에 의존하지 않음&lt;/b&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;서로 연관 및 의존하는 객체들의 그룹으로 생성해 추상적&lt;/span&gt;&lt;/b&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;빌더 (Builder)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;작게 분리된 인스턴스를 건축 하듯이 조합해 객체를 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;객체의 생성 과정, 표현 방법을 분리&lt;/span&gt;&lt;/b&gt;하고 있음.&lt;/li&gt;
&lt;li&gt;동일한 객체 생성에서도 서로 다른 결과를 만들 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;팩토리 메소드 (Factory Method)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Virtual Constructor(가상 생성자) 패턴&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;객체 생성을 서브 클래스&lt;/b&gt;&lt;/span&gt;에서 처리하도록 분리 후 캡슐화&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;상위 클래스에서 인터페이스만 정의&lt;/span&gt;&lt;/b&gt;하고 실제 생성은 서브 클래스가 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로토타입 (Prototype)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;원본 객체를 복제&lt;/b&gt;&lt;/span&gt;하는 방법&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;객체를 생성하는 패턴으로 일반적인 방법&lt;/span&gt;&lt;/b&gt;으로 객체를 생성 - new&lt;/li&gt;
&lt;li&gt;비용이 큰 경우 주로 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;싱글톤 (Singleton)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 객체를 생성하면 생성된 객체를 어디서든 참조할 수 잇다.&lt;/li&gt;
&lt;li&gt;여러 프로세스가 동시에 참조할 수는 없다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;클래스 내에서 인스턴스가 하나 뿐임을 보장&lt;/b&gt;&lt;/span&gt;해야한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;불필요한 메모리 낭비를 최소화&lt;/b&gt;&lt;/span&gt; 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;구조 패턴(Structural Pattern)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;구조가 복잡한 시스템을 개발하기 쉽도록 클래스나 객체들을 조합하여 더 큰 구조로 만듬&lt;/li&gt;
&lt;li&gt;어댑터 (Adapter)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;호환성이 없는 클래스들의 인터페이스를 다른 클래스가 이용할 수 있도록 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;변환&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;기존의 클래스를 이용하고 싶지만 인터페이스가 일치하지 않을 때, 어댑터로 변환해서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;브리지 (Bridge)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;구현부에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;추상층을 분리&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;서로가 독립적으로 확장&lt;/span&gt;&lt;/b&gt;할 수 있도록 구성한 패턴&lt;/li&gt;
&lt;li&gt;기능과 구현을 두 개의 별도 클래스로 구현한다.&lt;/li&gt;
&lt;li&gt;Spring 에서 Repository, Controller에서 다른 Interface를 사용하는데 브리지로 되어있는거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;컴포지트 (Composite)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;여러 객체를 가진 복합 객체와 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;단일 객체를 구분 없이 다룰 때 사용&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;객체들을 트리 구조로 구성&lt;/span&gt;&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;디렉터리 안에 디렉터리가 있듯, 복합 객체 안 복합 객체가 포함되도록 구조 가능&lt;/li&gt;
&lt;li&gt;List&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데코레이터 (Decorator)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;객체 간의 결합을 통해 능동적으로 기능들을 확장할 수 있는 패턴&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;임의의 객체에 부가적인 기능을 추가&lt;/span&gt;&lt;/b&gt;함.&lt;/li&gt;
&lt;li&gt;다른 객체들을 덧붙이는 방식으로 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;퍼싸드(Facade)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;복잡한 서브 클래스들을 피해 더 상위에 인터페이스를 구현&lt;/li&gt;
&lt;li&gt;서브 클래스들의 기능을 간편하게 사용할 수 있음.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;서브 클래스들 사이 통합 인터페이스를 제공하는 Wrapper 객체가 필요&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;플라이웨이트(Flyweight)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인스턴스가 필요할 때 마다 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;매번 생성하지 않음&lt;/b&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;가능한 공유해서 사용하면서 메모리를 절약&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;다수의 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;유사 객체를 생성하거나 조작&lt;/span&gt;&lt;/b&gt;할 때 유용함.&lt;/li&gt;
&lt;li&gt;MAP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프록시 (Proxy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;접근이 어려운 객체와 접근이 어려운 객체에 연결하려는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;객체 사이에서 인터페이스&lt;/span&gt;&lt;/b&gt;를 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;행위 패턴 (Behavioral Pattern)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;클래스나 객체들이 서로 상호작용하는 방법이나 책임 분배 방법을 정의하는 패턴
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;책임 연쇄(Chain Of Responsibility)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요청을 처리할 수 있는 객체가 둘 이상 존재할&lt;/span&gt;&lt;/b&gt; 때&lt;/li&gt;
&lt;li&gt;한 객체는 요청을 처리하지 못한다면&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 다음 객체로 넘어가는 형태&lt;/b&gt;&lt;/span&gt;의 패턴&lt;/li&gt;
&lt;li&gt;요&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;청을 처리하는 각 객체가 Chain으로 묶여 있는 형태&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;요청이 해결 될 때까지 Chain을 따라 책임이 연쇄됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;커맨드 (Command)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;요청을 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;객체의 형태로 캡슐화하여 재이용, 취소, 저장, 기록&lt;/span&gt;&lt;/b&gt;을 하는 패턴&lt;/li&gt;
&lt;li&gt;요청에 사용되는 각종 명령을 추상 클래스와 구체 클래스로 분리해서 단순화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터프리터 (Interpreter)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;언어에 문법 표현을 정의, SQL 및 통신 프로토콜 개발 시 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;반복자 (Iterator)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자료구조와 같이 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;접근이 잦은 객체에 대해 동일한 인터페이스를 사용&lt;/span&gt;&lt;/b&gt;하도록 하는 패턴&lt;/li&gt;
&lt;li&gt;내부 표현 방법의 노출 없이 순차적 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;중재자 (Mediator)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;수많은 객체간 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;복잡한 상호작용을 캡슐화&lt;/span&gt;&lt;/b&gt;하여 객체로 정의&lt;/li&gt;
&lt;li&gt;객체 사이의 의존성을 줄여 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;결합도를 낮춤&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메멘토 (Memento)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;특정 시점에&lt;/b&gt;&lt;/span&gt;서의 객체 내부 상태를 객체화&lt;/li&gt;
&lt;li&gt;요청에 따라 객체를 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;해당 시점의 상태로 돌릴 수 있는 기능&lt;/span&gt; &lt;/b&gt;제공&lt;/li&gt;
&lt;li&gt;Ctrl + Z와 같은 되돌리기 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;옵저버 (Observer)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;한 객체의 상태가 변화하면 객체에 상속되어 있는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다른 객체들에게 변화된 상태&lt;/b&gt;&lt;/span&gt;를 전달&lt;/li&gt;
&lt;li&gt;일대다의 의존성을 정의&lt;/li&gt;
&lt;li&gt;분산 시스템 간 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;이벤트를 생성,발행(Publish)하고 수신(Subscribe)&lt;/span&gt;&lt;/b&gt;해야 할 때 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;상태 (State)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;객체의 상태에 따라 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;동일한 동작을 다르게 처리해야할 때&lt;/span&gt;&lt;/b&gt; 사용되는 패턴&lt;/li&gt;
&lt;li&gt;객체 상태를 캡슐화하고 이를&amp;nbsp; 참조하는 방식으로 처리&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전략 (Strategy)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;동일한 계열 알고리즘들을 개별적으로 캡슐화&lt;/b&gt;&lt;/span&gt;하여 상호 교환할 수 있게 정의&lt;/li&gt;
&lt;li&gt;클라이언트는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;독립적으로 원하는 알고리즘&lt;/span&gt;&lt;/b&gt; 선택 가능&lt;/li&gt;
&lt;li&gt;클라이언트에 영향 없이 알고리즘 변경 가능&lt;/li&gt;
&lt;li&gt;스프링의 DI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;템플릿 메소드 (Template Method)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;상위 클래스에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;골격을 정의&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;하위 클래스에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;세부 처리를 구체화 하는 구조&lt;/span&gt;&lt;/b&gt;의 패턴&lt;/li&gt;
&lt;li&gt;유사한 서브 클래스를 묶어 공통된 내용을 상위 클래스에서 정의&lt;/li&gt;
&lt;li&gt;코드의 양을 줄이고 유지보수를 용이하게 함&lt;/li&gt;
&lt;li&gt;Spring-tx&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;방문자 (Visitor)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;각 클래스들의 데이터 구조에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;처리 기능을 분리하여 별도의 클래스&lt;/span&gt;&lt;/b&gt;로 구성&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;분리된 처리 기능은 각 클래스를 방문&lt;/b&gt;&lt;/span&gt;하여 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;튜플 : 릴레이션을 구성하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;각각의 행&lt;/b&gt;&lt;/span&gt;, 파일 구조에서는 레코드에 해당&lt;/li&gt;
&lt;li&gt;속성 : 릴레이션을 구성하는&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 각각의 열&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;속성의 개수를 차수&lt;/b&gt;&lt;/span&gt;(Degree)라고 함.&lt;/li&gt;
&lt;li&gt;한 속성의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;필드를 제외한 릴레이션 인스턴스를 도메인&lt;/b&gt;&lt;/span&gt;이라고 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;릴레이션 인스턴스: 데이터 개체를 구성하고 있는 속성들에 데이터 타입이 정의되어 구체적인 값을 가진 것
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;실제 값&lt;/span&gt;&lt;/b&gt;을 가진 튜플을 의미, 테이블의 바디&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;릴레이션 스키마: 데이터 개체를 구성하고 있는 속성들의 데이터 타입이 정의 된 필드의 이름
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;테이블의 헤더, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;속성의 집합&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;카디널리티 : &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;튜플의 개수&lt;/b&gt;&lt;/span&gt; (기수, 대응수라고도 함)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;18번&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;외부 스키마
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;사용자나 응용 프로그래머가 개인의 입장&lt;/span&gt;&lt;/b&gt;에서 필요로 하는 DB의 논리적 구조를 정의&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;DB의 전체적인 논리적 구조&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;모든 응용프로그램이나 사용자&lt;/b&gt;&lt;/span&gt;가 필요로 하는 데이터를 종합한 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;전체 DB로 하나만 존재&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개체 간 관계와 제약 조건&lt;/b&gt;&lt;/span&gt;을 나타냄&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;DB의 접근 권한, 보안, 무결성 규칙에 대해 명세&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;ERD로 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;내부 스키마
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;물리적 저장장치의 입장에서 본 DB&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;실제로 DB에 저장될 레코드 형식을 정의&lt;/li&gt;
&lt;li&gt;저장될 데이터 항목의 표현 방법&lt;/li&gt;
&lt;li&gt;내부 레코드의 물리적 순서&lt;/li&gt;
&lt;li&gt;실제 DB에 셋팅, 인덱스 등을 추가해서 셋팅&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>2023년 1회차 정보처리기사</category>
      <category>2023년 정보처리기사</category>
      <category>23년 1회차 정처기</category>
      <category>ㅈ023년 1회차 정처기</category>
      <category>정보처리기사</category>
      <category>정보처리기사 실기</category>
      <category>정보처리기사 필기</category>
      <category>정처기</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/80</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-23%EB%85%84-1%ED%9A%8C-%EA%B8%B0%EC%B6%9C#entry80comment</comments>
      <pubDate>Fri, 26 Jul 2024 13:54:21 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 소프트웨어 구축 - 소프트웨어 설계</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;소프트웨어 설계 원리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;분할과 정복
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;여러개의 작은 시스템으로 나누고 각 각을 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모듈화 (Modulartly)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;시스템 기능을 모듈 단위로 분류 -&amp;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;추상화 (Abstraction)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;불필요한 부분은 생략, 필요한 부분만 강조&lt;/li&gt;
&lt;li&gt;문제의 포괄적인 개념 설계 -&amp;gt; 세분화 -&amp;gt; 구체화&lt;/li&gt;
&lt;li&gt;과정 추상화 : 전반적인 흐름만 파악가능하도록 설계&lt;/li&gt;
&lt;li&gt;데이터(자료) 추상화: 데이터의 세부적 속성이나 용도는 정의하지 않고 구조만 표현한다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;private 으로 외부에서는 이 정보를 모르고 생성자로 정보의 구조만 알려주고 캡슐화로 정보를 얻는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제어 추상화: 이벤트 발생의 정확한 절차나 방법은 정의하지 않는다. 대표 가능한 표현으로 대체한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721888893238&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 과정 추상화
abstract class CoffeeShop {
    void processOrder(CoffeeOrder order) {
        takeOrder(order);
        prepareCoffee(order);
        serveCoffee(order);
    }

    abstract void takeOrder(CoffeeOrder order);
    abstract void prepareCoffee(CoffeeOrder order);
    abstract void serveCoffee(CoffeeOrder order);
}

// 데이터 추상화
class CoffeeOrder {
    private String customerName;
    private String coffeeType;
    private int quantity;

    public CoffeeOrder(String customerName, String coffeeType, int quantity) {
        this.customerName = customerName;
        this.coffeeType = coffeeType;
        this.quantity = quantity;
    }

    public String getCustomerName() {
        return customerName;
    }

    public String getCoffeeType() {
        return coffeeType;
    }

    public int getQuantity() {
        return quantity;
    }
}

// 제어 추상화
interface Button {
    void onClick();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;단계적 분해 (Stepwise refinement)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하향식 설계 전략으로 추상화를 반복해서 세분화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;정보 은닉 (Information Hiding)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다른 모듈의 접근/ 변경 불가&lt;/li&gt;
&lt;li&gt;모듈이 독립적이라 요구사항에 따라 수정/테스트/유지보수 용이&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UML (Unified Modeling Language)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;고객/개발자 간 워놜한 소통을 위해 표준화된 대표적 객체지향 모델링 언어&lt;/li&gt;
&lt;li&gt;Rumbaugh, Booch, Jacobson 등 객체지향 방법론의 장점을 통합함.&lt;/li&gt;
&lt;li&gt;사물 (Things)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;구조 (개념, 물리적 요소), 행동, 그룹, 주해(부가적 설명, 제약조건)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;관계 (Relationship)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;연관 관계 (Association)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;2개 이상의 사물이 서로 연관 된 경우, 양방향 or 단방&lt;/li&gt;
&lt;li&gt;다른 클래스의 정보를 사용할 수 있는 경우&lt;/li&gt;
&lt;li&gt;private void setOtherclass(OtherClass other) { this.other = other; }&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;집합 관계 (aggregation)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 사물이 다른 사물에 포함된 경우 (전체-부분 관계)&lt;/li&gt;
&lt;li&gt;즉, 다른 클래스가 꼭 있어야 완성 되는 경우&lt;/li&gt;
&lt;li&gt;private OtherClass other = other;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;포함 관계 (Composition)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;집합 관계 내 한 사물의 변화가 다른 사물에게 영향&lt;/li&gt;
&lt;li&gt;다른 클래스가 있어야 완성되지만 다른 클래스가 나에게 종속된 경우&lt;/li&gt;
&lt;li&gt;내가 사라지면 다른 클래스도 사라짐.&lt;/li&gt;
&lt;li&gt;private OtherClass other = new OtherClass();&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일반화 관계 (Generalization)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다른 사물에 비해 일반적인지 구체적인지 표현&lt;/li&gt;
&lt;li&gt;상속 개념 extends&lt;/li&gt;
&lt;li&gt;Child extends Parent&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;의존 관계 (Dependency)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사물 간 서로 영향을 주는 관계&lt;/li&gt;
&lt;li&gt;한 클래스에서 다른 클래스의 기능을 사용&lt;/li&gt;
&lt;li&gt;public print(OtherPrint print) { print.print(); }&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실체화 관계 (Realization)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;한 객체가 다른 객체에게 오퍼레이션을 수행하도록 지정&lt;/li&gt;
&lt;li&gt;인터페이스를 구현&lt;/li&gt;
&lt;li&gt;implements OtherClass&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다이어그램 (Diagram)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;구조, 정적 다이어 그램
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;클래스 : 클래스 간 관계, 클래스의 변수 자료형, 변수명 정보&lt;/li&gt;
&lt;li&gt;객체 : 인스턴스를 객체, 객체의 값 정보&lt;/li&gt;
&lt;li&gt;컴포넌트 : 구현 모듈 간 관계&lt;/li&gt;
&lt;li&gt;배치 : 물리적 요소의 위치/구조 표현 Server 에서 어떤 정보가 Client에게 어떤 정보로&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;유스케이스 : 사용자 + Use Case&lt;/li&gt;
&lt;li&gt;시퀀스 : 시스템과 객체가 주고 받는 메시지 표현&lt;/li&gt;
&lt;li&gt;커뮤니케이션: 객체들 간 주고 받는 메시지와 연관관계&lt;/li&gt;
&lt;li&gt;상태: 다른 객체와 상호작용에 따른 상태 변화&lt;/li&gt;
&lt;li&gt;활동 : 객체의 처리 로직, 조건에 따른 처리의 흐름 순서에 따라 표현&lt;/li&gt;
&lt;li&gt;타이밍: 객체 상태 변화, 시간 제약을 표현&lt;/li&gt;
&lt;li&gt;상호작용 개요 : 상호작용 다이어그램 간 제어 흐름 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;UI 설계 (User Interface)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;직관성, 유효성, 학습성, 유연성&lt;/li&gt;
&lt;li&gt;CLI(command line), GUI(graphic), NUI(natural), VUI(voice), OUI(organic)&lt;/li&gt;
&lt;li&gt;Wireframe : 기획 초 대략적인 레이아웃 설계&lt;/li&gt;
&lt;li&gt;Story Board: 최종적 산출 문서 (와이어프레임 UI, 프로세스)&lt;/li&gt;
&lt;li&gt;Prototype : 와이어프레임 / 스토리보드에 인터렉션(동적 효과) 적용&lt;/li&gt;
&lt;li&gt;Mockup : 실제 화면과 유사한 정적인 형태 모형&lt;/li&gt;
&lt;li&gt;Use case : 사용자 측면 요구사항 및 목표를 다이어그램으로 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>자격증/정보처리기사</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/79</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84#entry79comment</comments>
      <pubDate>Thu, 25 Jul 2024 16:39:03 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 소프트웨어 구축 - 요구사항 분석</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%EB%B6%84%EC%84%9D</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;요구사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 문제를 해결하기 위해 필요한 조건, 제약사항을 요구&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SW 개발/유지 보수 과정에 필요한 기준과 근거를 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;요구사항의 유형
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;도출/추출 : 이해관계자 간 요구사항을 정의 (식별 및 이해)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터뷰, 설문, 브레인스토밍, 청취, 프로토타이핑, 유스케이스&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;분석: 사용자 요구사항에 타당성 조사 및 비용 및 일정에 대한 제약 설정
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;관찰, 개념 모델링, 정형 분석, 요구사항 정의 문서화&lt;/li&gt;
&lt;/ul&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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;요구사항 분석 CASE(Computer Aided SW Engineering)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SADT : 구조적 분석 및 설계 분석, 블록 다이어 그램&lt;/li&gt;
&lt;li&gt;SREM : 실시간 처리 시스템에서 요구사항을 명확하게 기술&lt;/li&gt;
&lt;li&gt;PSL/PSA : 문제 기술언어/요구사항 분석 보고서 출력&lt;/li&gt;
&lt;li&gt;TAGS: 시스템 공학 방법 응용에 대한 자동 접근, 개발 주기 전 과정에 이용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;구조적 분석 모델&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터/자료 흐름도 (DFD, Data Flow Diagram)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;원 - 프로세스&lt;/li&gt;
&lt;li&gt;화살표 - 흐름&lt;/li&gt;
&lt;li&gt;평행선 - 자료 저장소 (DB, Memory)&lt;/li&gt;
&lt;li&gt;단말 - Terminator (done)&lt;/li&gt;
&lt;li&gt;시간 흐름을 명확하게 표현할 수 없음 버블 차트라고도 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721887698698&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;+-----------------+     +-----------------+
| External Entity |--&amp;gt;--|     Process     |--&amp;gt;--[Data Store]
+-----------------+     +-----------------+
       ^
       |
+-----------------+
| Data Flow       |
+-----------------+&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자료 사전 (DD, Data Dictionary)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자료 흐름도의 내용을 상세 정의/상세 설명&lt;/li&gt;
&lt;li&gt;[] : 선택&lt;/li&gt;
&lt;li&gt;() : 생략&lt;/li&gt;
&lt;li&gt;{} : 반복&lt;/li&gt;
&lt;li&gt;+ : 구성&lt;/li&gt;
&lt;li&gt;= : 정의&lt;/li&gt;
&lt;li&gt;** : 주석&lt;/li&gt;
&lt;li&gt;DFD의 소단위 명세서이며 ERD와 STD와 같이 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721886469725&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;External Entity: 고객(Customer)
Process: 주문 처리(Order Processing)
Data Store: 주문 데이터베이스(Order Database)
Data Flow: 주문 요청(Order Request)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;ERD&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721886484589&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;+----------------+     +----------------+
|     Customer   |-----|      Order     |
|----------------|  1  |----------------|
| CustomerID     |     | OrderID        |
| Name           |     | CustomerID     |
| Address        |     | OrderDate      |
+----------------+     +----------------+&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;STD&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721886501093&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;+-------------+     +-------------+     +-------------+
|  상태: 대기  |----|  이벤트: 주문  |----|  상태: 처리 중 |
+-------------+     +-------------+     +-------------+
                         |
                    +-------------+
                    |  이벤트: 취소  |
                    +-------------+
                         |
                    +-------------+
                    |  상태: 취소됨  |
                    +-------------+&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;객체지향 분석 모델&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Booch(부치) : 미시적, 거시적 개발 프로세스를 모두 사용해서 클래스 분석 및 식별&amp;nbsp;거시적&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721887778568&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;거시적
+---------------------------+
|  온라인 도서 판매 시스템   |
+---------------------------+
|  사용자 인터페이스         |
|  주문 처리 시스템          |
|  결제 시스템               |
|  데이터베이스              |
+---------------------------+
미시적
Class: User
Attributes: userID, name, email, password
Methods: register(), login(), updateProfile()

Class: Book
Attributes: bookID, title, author, price
Methods: addBook(), updateBook(), deleteBook()

Class: Order
Attributes: orderID, userID, bookID, orderDate, status
Methods: createOrder(), updateOrder(), cancelOrder()&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Jacobson(제이콥슨): Use Case를 사용 (사용자와 외부 시스템이 시스템과 상호 작용)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721887844574&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;사용자 기능 명세
+---------------------------+
|  온라인 도서 판매 시스템  |
+---------------------------+
| 1. 책 검색                |
| 2. 책 주문                |
| 3. 결제 처리              |
| 4. 주문 확인              |
+---------------------------+

유스케이스
          +------------+
          |  사용자    |
          +------------+
                |
                v
  +---------------------------+
  | 온라인 도서 판매 시스템   |
  +---------------------------+
  | 1. 책 검색                |
  | 2. 책 주문                |
  | 3. 결제 처리              |
  | 4. 주문 확인              |
  +---------------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Coad-Yourdon : E-R 다이어그램, 객체의 행위&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721887892147&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;E-R 다이어그램
+------------+            +------------+          +------------+
|    User    |            |    Book    |          |   Order    |
+------------+            +------------+          +------------+
| userID     | &amp;lt;--------- | bookID     | &amp;lt;--------|  orderID   |
| name       | 1 : M      | title      | N : M    |  userID    |
| email      |            | author     |          |  bookID    |
| password   |            | price      |          |  orderDate |
+------------+            +------------+          |  status    |
                                                  +------------+&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Wirfs-Brock : 분석, 설계 간 구분이 없다. 고객 명세서 평가 후 설계 작업까지 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721887940820&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;+---------------------------+
|  고객 명세서 평가 후 설계 |
+---------------------------+
| - 책 검색 기능            |
| - 책 주문 기능            |
| - 결제 처리 기능          |
| - 주문 확인 기능          |
+---------------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Rumbaugh (럼바우) : 가장 일반적으로 사용한다. 객체/동적/기능 모델
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;객체 모델링 -&amp;gt; Object Diagram 객체 간의 관계&lt;/li&gt;
&lt;li&gt;동적 모델링 -&amp;gt; Dynamic, 상태 다이어그램 / 시스템의 동적인 행위&lt;/li&gt;
&lt;li&gt;기능 모델링 -&amp;gt; 자료 흐름도 DFD / 다수의 프로세스 처리 과정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721888392606&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;객체 모델링
+------------+            +------------+            +------------+
|    User    |            |    Book    |            |   Order    |
+------------+            +------------+            +------------+
| userID     | &amp;lt;--------- | bookID     | &amp;lt;--------- |  orderID   |
| name       |   1 : N    | title      |   N : M    |  userID    |
| email      |            | author     |            |  bookID    |
| password   |            | price      |            |  orderDate |
+------------+            +------------+            |  status    |
                                                    +------------+
동적 모델링
[Order Created] --&amp;gt; [Order Confirmed] --&amp;gt; [Order Shipped] --&amp;gt; [Order Delivered]
     |                      |                     |                  |
     v                      v                     v                  v
[Order Cancelled]    [Payment Failed]     [Order Returned]    [Order Completed]

기능 모델링

+-----------------+
|  Search Books   |
+-----------------+
       |
       v
+-----------------+       +-----------------+
|  Select Book    | &amp;lt;---&amp;gt; |  Add to Cart    |
+-----------------+       +-----------------+
       |
       v
+-----------------+       +-----------------+
|  Create Order   | &amp;lt;---&amp;gt; |  Payment Process |
+-----------------+       +-----------------+
       |
       v
+-----------------+
|  Confirm Order  |  ---&amp;gt;  [ Data Stroe ]
+-----------------+&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;요구사항 명세
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;정형 명세&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;수학적 원리&lt;/li&gt;
&lt;li&gt;정확하고 간결한 요구사항이 표현 됨&lt;/li&gt;
&lt;li&gt;대신 어려워서 사용자가 이해하기 어려움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;비정형 명세
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&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;</description>
      <category>자격증/정보처리기사</category>
      <category>객체지향 분석</category>
      <category>구조적 분석</category>
      <category>소프트웨어 구축</category>
      <category>소프트웨어 생명 주기</category>
      <category>요구사항 명세</category>
      <category>요구사항 분석</category>
      <category>정보처리기사</category>
      <category>정보처리기사 실기</category>
      <category>정보처리기사 필기</category>
      <category>정처기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/78</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%EB%B6%84%EC%84%9D#entry78comment</comments>
      <pubDate>Thu, 25 Jul 2024 15:21:51 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 소프트웨어 구축 - 프로젝트 계획</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B3%84%ED%9A%8D</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 계획할 때는 개발 예산을 생각해서 비용을 추정하고 개발을 할 지 말 지부터 정해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 하겠다고 마음을 먹었으면 이제 개발 일정을 고려해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;비용산정&lt;/b&gt;&lt;/blockquote&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;전반적인 지식과 경험이 있기 때문에 실제 개발을 시작하기 전에 틀이 잡힌다.&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;/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;LOC (source Line Of Code)&amp;nbsp;
&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;낙관치(a), 비관치(b), 기대치(c)를 예측해서 비용을 산정한다.&lt;/li&gt;
&lt;li&gt;(a + b + 4c) / 6&lt;/li&gt;
&lt;li&gt;필요하다고 예측이 되는 모듈과 비슷한 모듈이나 하향식 비용 산정으로 계산할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개발 단계별 인월 수 (Effort Per Task)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LOC를 보완한 방법으로 생명 주기 각 단계별로 비용을 산정한다.&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;COCOMO(Constructive Cost Model)
&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;조직형 (Organic) : 인트라넷과 같이 일정 조직 내에서만 사용하는 SW, 원시코드가 적다&lt;/li&gt;
&lt;li&gt;반분리형 (Semi-detached) : 기업용 SW, 일반적으로 트래픽이 많은 것들
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라 &amp;lt;-&amp;gt; 서버의 구조로 분리된 인터넷을 사용하는 큰 프로그램으로 생각&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;내장형 (Embedded): SW가 탑재된 것, 비행기나 자동차 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PUTNAM
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SW 생명주기 전 과정에서 사용될 노력의 분포를 이용&lt;/li&gt;
&lt;li&gt;노던 레일리 곡선의 노력 분포도를 기초로 한다.&lt;/li&gt;
&lt;li&gt;SLIM 이라는 자동화 도구로 비용을 예측, PUTNAM 기반&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Function Point (FP), 중요한 요인에 가중치를 부여 -&amp;gt; 합산 -&amp;gt; 기능 점수 산출
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SW 기능 증대 요인(자정인데명) - 자료 입력/정보출력/인터페이스/데이터 파일/명령어&lt;/li&gt;
&lt;li&gt;ESTIMACS 이라는 자동화 도구가 FP 기반&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;개발 일정 산정&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;WBS(Work Breakdown Structure)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 목표 달성을 위한 활동, 업무를 세분화&lt;/li&gt;
&lt;li&gt;전체 프로젝트를 분할 후 수행 업무를 식별하고 일정과 비용을 산출&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;네트워크 차트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PERT (Program Evaluation and Review Technique)
&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;CPM (Critical Path Method)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드(작업)과 간선(작업 전후 의존관계)/박스(이정표)로 구성&lt;/li&gt;
&lt;li&gt;간선의 흐름에 따라 작업을 진행&lt;/li&gt;
&lt;li&gt;확실한 상황에서 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eLahcw/btsILhFxkyR/4tVJv3dPCqsNcxoC5RBFX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eLahcw/btsILhFxkyR/4tVJv3dPCqsNcxoC5RBFX0/img.png&quot; data-alt=&quot;CPM. 임계 경로 : 14일 (A-B-E-G-H), 가장 오래 걸리는 시간&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eLahcw/btsILhFxkyR/4tVJv3dPCqsNcxoC5RBFX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeLahcw%2FbtsILhFxkyR%2F4tVJv3dPCqsNcxoC5RBFX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;588&quot; height=&quot;182&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CPM. 임계 경로 : 14일 (A-B-E-G-H), 가장 오래 걸리는 시간&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간트 차트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 작업의 시작/종료 일정을 바로 표현한다.&lt;/li&gt;
&lt;li&gt;시간선 차트&lt;/li&gt;
&lt;li&gt;작업 경로는 표현이 불가능해서 계획 변화에 대한 적응성이 낮다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSQ1Va/btsILixIA7Y/qcElK6QfnI2nzUJ365XY9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSQ1Va/btsILixIA7Y/qcElK6QfnI2nzUJ365XY9k/img.png&quot; data-alt=&quot;간트차트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSQ1Va/btsILixIA7Y/qcElK6QfnI2nzUJ365XY9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSQ1Va%2FbtsILixIA7Y%2FqcElK6QfnI2nzUJ365XY9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;486&quot; height=&quot;297&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;간트차트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>SDLC</category>
      <category>sw 구축</category>
      <category>비용 산정</category>
      <category>소프트웨어 구축</category>
      <category>소프트웨어 생명 주기</category>
      <category>일정 산출</category>
      <category>정보처리기사</category>
      <category>정보처리기사 실기</category>
      <category>정보처리기사 필기</category>
      <category>프로젝트 계획</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/77</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B3%84%ED%9A%8D#entry77comment</comments>
      <pubDate>Thu, 25 Jul 2024 14:20:39 +0900</pubDate>
    </item>
    <item>
      <title>[실기] 소프트웨어 구축 - SW 설계</title>
      <link>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-SW-%EC%84%A4%EA%B3%84</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 생명 주기 (Software Development Life Cycle, SDLC)
&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;설계 : 분석한 사항을 바탕으로 아키텍쳐, 디자인, DB 등을 설계&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;폭포수 모델 (Waterfall Model)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대규모에 사용되는 고전적인 SDLC 모델이다.&lt;/li&gt;
&lt;li&gt;SDLC의 프로세스를 선형적으로 처리한다.&lt;/li&gt;
&lt;li&gt;SW 프로세스는 선형적일 수 없다. 수정 사항이 생길 경우 이전 내역이 사라질 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로토 타입 모델 (Prototype Model)
&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;Dev Class와 Release Class&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;나선형 모델 (Spiral Model)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;폭포수 모델, 프로토 타입 모델의 이점에 위험 분석 기능을 추가한 방법이다.&lt;/li&gt;
&lt;li&gt;계획 수립 : 프로젝트 계획 + 요구사항 분석&lt;/li&gt;
&lt;li&gt;위험 분석 : 위험식별, 정량적/정성적 평가, 그에 따른 결과 + 설계&lt;/li&gt;
&lt;li&gt;개발 및 검증 : 구현 + 테스트&lt;/li&gt;
&lt;li&gt;고객 평가 : 유지보수&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;애자일 (Agile)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일정한 짧은 주기(Sprint or Iteration)만큼 반복해서 개발을 진행한다.&lt;/li&gt;
&lt;li&gt;고객과의 소통을 중시해서 고객 요구사항에 유연하게 대응할 수 있다.&lt;/li&gt;
&lt;li&gt;XP, Scrum, Function Driven Design, Lean, Dynamic System Development Method 등이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;XP(eXtream Programming)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;5가지의 가치와 12개의 실천 항목이 있고 의사소통을 개선하고 즉각적인 피드백을 하기위한 설계 방법론&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;즉, 고객 요구사항을 유연하게 대응하기 위해 24시간 상주할 수 있는 고객과 함께 신속한 개발을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;5가지 핵심 가치&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;용기 (Courage)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;단순성 (Simplicty)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;의사소통 (Commnuication)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;피드백 (Feedback)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;존중 (Respect)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;12가지 기본 원리&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Planning Process&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Pair Programming&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;CI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Refactoring&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;On Suit Customer&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Coding standard&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;TDD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Simple Design&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Small Release&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Metaphore&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;Collective Ownership&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하향식 설계 (Top-down)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;절차 지향의 순차적 설계법&lt;/li&gt;
&lt;li&gt;최상위 컴포넌트 -&amp;gt; 하위 기능 부여 -&amp;gt; 테스트 초기부터 사용자에게 구조 제시 가능&lt;/li&gt;
&lt;li&gt;main 또는 객체에서 필요한 것들을 순서대로 코드로 작성하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;상향식 설계 (Bottom-up)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 지향의 설계&lt;/li&gt;
&lt;li&gt;최하위 모듈 설계 -&amp;gt; 결합 및 검사 -&amp;gt; 인터페이스 구조 변경 시 상위 모듈도 같이 변경이 필요&lt;/li&gt;
&lt;li&gt;사칙연산을 하는 프로그램은 숫자 2개의 입력을 필요로 한다. 제곱근을 구하는 모듈을 추가한다면 숫자 1개의 입력을 필요로 한다. 이로 인해 인터페이스의 구조가 변경되고 이를 사용하던 상위 모듈 또한 변경해줘야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1721881466363&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# command 에 따라 사칙연산
def inputNum():
    a = int(input());
    b = int(input());
    return a, b;

command = input();
a, b = inputNum();
print(cal(a, b, command));

# 위 코드에서 command 제곱근을 추가했을 경우
def inputNum(command):
    a = int(input());
    if (command == 'sqrt') return a;
    b = int(input());
    return a, b;

if command == 'sqrt':
    num = inputNum(command);
    print(cal(num, 0, command));
else:
    a, b = inputNum(command);
    print(cal(a, b, command));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 막 쓸데 없는 코드도 추가 된다. 이런 부분을 개선하기 위해 나타난게 디자인 패턴이다.&lt;/p&gt;</description>
      <category>자격증/정보처리기사</category>
      <category>Software Engineering</category>
      <category>sw 공학</category>
      <category>SW 설계</category>
      <category>생명주기</category>
      <category>소웨공</category>
      <category>소프트웨어 구축</category>
      <category>애자일</category>
      <category>정보처리기사</category>
      <category>정처기 실기</category>
      <category>정처기 필기</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/76</guid>
      <comments>https://dev-dot.tistory.com/entry/%EC%8B%A4%EA%B8%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B5%AC%EC%B6%95-SW-%EC%84%A4%EA%B3%84#entry76comment</comments>
      <pubDate>Thu, 25 Jul 2024 13:28:16 +0900</pubDate>
    </item>
    <item>
      <title>10. Casting (형변환)</title>
      <link>https://dev-dot.tistory.com/entry/10-Casting-%ED%98%95%EB%B3%80%ED%99%98</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Casting 이란?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료형에서 다른 자료형으로 바꾸는 과정을 Casting(형변환)이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dev-dot.tistory.com/entry/3-%EC%9E%90%EB%A3%8C%ED%98%95DataType&quot;&gt;3. 자료형&lt;/a&gt; 포스트에서 확인할 수 있듯이 각 자료형은 변수를 선언할 때, 자료형 크기 만큼 공간을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 공간에 값을 넣음으로써 할당이 되는데 Casting도 같은 원리이다.&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;long a - [size = 8], int b - [size = 4] 이미 a와 b를 선언하는 순간부터 컴퓨터 메모리에는 저 공간이 할당이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, b에 있는 데이터를 a에 넣어봤자 8개의 size 중 4개의 size만 사용하므로 아무 문제가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 원리 때문에 Casting이 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;작은 Data type 에서 큰 Data type만?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시만 보면 크기가 더 작은 자료형에서 더 큰 자료형으로 대입할 때만 Casting이 되는 것이냐고 생각할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저것은 당연한 과정이라 자동으로 수행된다고 해서 자동 형변환이라고 하고 묵시적 형변환이라고도 한다. 영어로는 UpCasting 이라고 한다. 더 커졌으므로&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;하지만, 큰 Data Type에서도 작은 Data Type으로 형변환을 할 수 있는데 이것을 DownCasting 이라고 하고 강제 형변환, 명시적 형변환이라고 한다. 명시적 형변환이라고 하는 이유는 바꾼다고 명시해줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720969096435&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;long a = Integer.MAX_VALUE;
int b = (int) a;&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;코드와 같이 어떤 자료형으로 바꿀 것인지 명시해야 한다. 다만 작은 Data Type의 경우, 한계값이 있기 때문에 이것을 초과하는 경우 OverFlow가 발생한다. OverFlow는 작은 DataType의 가장 작은 값부터 초과된 값까지 채워지는데 이 과정을 생각 조차도 하면 안된다.&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;그냥 OverFlow 자체가 문제이므로 명시적 형변환을 할 때는 제한을 확실하게 생각해두자.&lt;/p&gt;</description>
      <category>JAVA/기본 이론</category>
      <category>basic java</category>
      <category>casting</category>
      <category>downcasting</category>
      <category>overflow</category>
      <category>upcasting</category>
      <category>자료형</category>
      <category>자바</category>
      <category>자바 기본</category>
      <category>캐스팅</category>
      <category>형변환</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/75</guid>
      <comments>https://dev-dot.tistory.com/entry/10-Casting-%ED%98%95%EB%B3%80%ED%99%98#entry75comment</comments>
      <pubDate>Sun, 14 Jul 2024 23:59:51 +0900</pubDate>
    </item>
    <item>
      <title>[MST] 최소 스패닝 트리 - 크루스칼(Kruskal), 프림(Prim)</title>
      <link>https://dev-dot.tistory.com/entry/MST-%EC%B5%9C%EC%86%8C-%EC%8A%A4%ED%8C%A8%EB%8B%9D-%ED%8A%B8%EB%A6%AC-%ED%81%AC%EB%A3%A8%EC%8A%A4%EC%B9%BCKruskal-%ED%94%84%EB%A6%BCPrim</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;MST란?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 신장 트리(Minimum Spanning Tree)로 가중 그래프(Weight Graph)에서 가장 적은 비용(Weight)으로 모든 정점(Vertex)으로 이동할 수 있는 부분 그래프(Sub Graph)이다. MST는 각 정점에서 정점 사이에 하나의 간선(Edge)만 필요하므로 총 N-1 개의 간선을 가지게 되므로 마치 트리의 형태를 하고 있어서 트리라는 이름이 붙는다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;크루스칼 알고리즘&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 모든 간선을 비용이 적은 순서를 기준으로 정렬한다. - Sort&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 간선에 붙은 정점 u와 v를 기준으로 부모를 찾는다. - Find&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 정점 u의 부모와 정점 v의 부모가 다르다면 서로 다른 집합에 속해있지만, 1번 과정으로 인해 해당 간선이 두 정점의 최소 비용의 간선임을 알 수 있으므로 하나의 집합으로 합친다. - Union&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;+ Union 과정에서 이어진 간선이 최소 비용이므로 해당 간선 정보로 MST의 총 비용이나 경로를 알 수 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 1번 Sort하는 과정을 배열로 할 수도 있지만, Priority Queue로도 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;크루스칼 노드&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720705127018&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.kruskal;

public class KruskalNode implements Comparable&amp;lt;KruskalNode&amp;gt; {

    int u;
    int v;
    int weight;

    public KruskalNode(int u, int v, int weight) {
        this.u = u;
        this.v = v;
        this.weight = weight;
    }

    @Override
    public int compareTo(KruskalNode o) {
        return this.weight - o.weight;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬을 위해 Comparable 인터페이스의 메소드를 구현해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Kruskal Algorithm - Array&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720705196436&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.kruskal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class ArrayKruskal {

    private List&amp;lt;KruskalNode&amp;gt; edges;
    private int[] parent, ranks;
    private int minimumDistance;
    private Set&amp;lt;Integer&amp;gt; path;

    public ArrayKruskal(int size) {
        this.edges = new ArrayList&amp;lt;&amp;gt;();
        this.parent = new int[size + 1];
        this.ranks = new int[size + 1];
        this.minimumDistance = Integer.MAX_VALUE;
        this.path = new LinkedHashSet&amp;lt;&amp;gt;();
        initParent(size + 1);
    }

    public void update() {
        this.minimumDistance = 0;
        Collections.sort(this.edges);
        for (KruskalNode node : this.edges) {
            int parentA = find(node.u);
            int parentB = find(node.v);
            if (parentA != parentB) {
                union(parentA, parentB);
                this.minimumDistance += node.weight;
                this.path.add(node.u);
                this.path.add(node.v);
            }
        }
    }

    public int getMinimumDistance() {
        return minimumDistance;
    }

    public void printTrace() {
        System.out.println(path.toString());
    }

    public void add(int u, int v, int w) {
        this.edges.add(new KruskalNode(u, v, w));
    }

    private void initParent(int size) {
        for (int i = 0; i &amp;lt; size; i++) {
            this.parent[i] = i;
            this.ranks[i] = 0; // rank 초기화
        }
    }

    private int find(int x) {
        if (x != parent[x]) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }

    private void union(int x, int y) {
        if (ranks[x] &amp;lt; ranks[y]) {
            int temp = ranks[x];
            ranks[x] = ranks[y];
            ranks[y] = temp;
        }

        parent[y] = x;

        if(ranks[x] == ranks[y]) {
            ranks[x] = ranks[y] + 1;
        }
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. find 연산은 부모를 찾을 때까지 recursion을 진행한다. (성능 개선, 경로압축 기법 적용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 정점 u와 정점 v가 다를 경우 Union 연산이 진행된다. 이 때, Rank로 트리의 높이를 저장하면서 각 tree의 계층을 표현할 수 있다. (Union 연산의 개선)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Set 자료구조를 이용해 Union 연산마다 매 노드를 추가해 중복된 노드는 무시하고 경로를 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Kruskal Algorithm - Priority Queue&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720705743087&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.kruskal;

import java.util.LinkedHashSet;
import java.util.PriorityQueue;
import java.util.Set;

public class PriorityQueueKruskal {

    private PriorityQueue&amp;lt;KruskalNode&amp;gt; edges;
    private Set&amp;lt;Integer&amp;gt; path;
    private int[] parent, ranks;
    private int minimumDistance;

    public PriorityQueueKruskal(int size) {
        this.edges = new PriorityQueue&amp;lt;&amp;gt;();
        this.parent = new int[size + 1];
        this.ranks = new int[size + 1];
        this.minimumDistance = Integer.MAX_VALUE;
        this.path = new LinkedHashSet&amp;lt;&amp;gt;();
        initParent(size + 1);
    }

    public void update() {
        this.minimumDistance = 0;
        PriorityQueue&amp;lt;KruskalNode&amp;gt; temp = new PriorityQueue&amp;lt;&amp;gt;(this.edges);
        while (!temp.isEmpty()) {
            KruskalNode node = temp.poll();
            int parentA = find(node.u);
            int parentB = find(node.v);
            if (parentA != parentB) {
                union(parentA, parentB);
                this.minimumDistance += node.weight;
                this.path.add(node.u);
                this.path.add(node.v);
            }
        }
    }

    public int getMinimumDistance() {
        return minimumDistance;
    }

    public void printTrace() {
        System.out.println(path.toString());
    }

    public void add(int u, int v, int w) {
        this.edges.add(new KruskalNode(u, v, w));
    }

    private void initParent(int size) {
        for (int i = 0; i &amp;lt; size; i++) {
            this.parent[i] = i;
        }
    }

    private int find(int x) {
        if (x == parent[x]) {
            return x;
        }
        return parent[x] = find(parent[x]);
    }

    private void union(int x, int y) {
        if (x == y) {
            return;
        }

        if (ranks[x] &amp;lt; ranks[y]) {
            int temp = ranks[x];
            ranks[x] = ranks[y];
            ranks[y] = temp;
        }

        parent[y] = x;

        if(ranks[x] == ranks[y]) {
            ranks[x] = ranks[y] + 1;
        }
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Priority Queue는 poll 연산을 통해 최소 신장 트리를 갱신할 수 있지만, 일회용이므로 복사하게 되는 시간이 발생한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 따로 정렬 객체를 부르지 않아도 된다는 장점이 있지만 음.. Priority Queue가 편하면 이 방법을, 아니면 ArrayList 방법을 사용할 수 있도록 하려고 두가지 방법을 다 작성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;실사용 Main&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720705962789&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.kruskal;

public class Main {

    public static void main(String[] args) {
        PriorityQueueKruskal pKruskal = new PriorityQueueKruskal(5);
        pKruskal.add(1, 2, 6);      pKruskal.add(1, 3, 3);
        pKruskal.add(1, 4, 1);      pKruskal.add(2, 5, 4);
        pKruskal.add(3, 4, 2);      pKruskal.add(3, 5, 5);
        pKruskal.add(4, 5, 7);      pKruskal.update();

        System.out.println(pKruskal.getMinimumDistance());
        pKruskal.printTrace();

        ArrayKruskal aKruskal = new ArrayKruskal(5);
        aKruskal.add(1, 2, 6);      aKruskal.add(1, 3, 3);
        aKruskal.add(1, 4, 1);      aKruskal.add(2, 5, 4);
        aKruskal.add(3, 4, 2);      aKruskal.add(3, 5, 5);
        aKruskal.add(4, 5, 7);      aKruskal.update();

        System.out.println(aKruskal.getMinimumDistance());
        aKruskal.printTrace();
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프림 알고리즘&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 모든 간선이 비용이 적은 순서로 정렬한다. - Sort&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 시작 정점을 정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 시작 정점으로부터 방문하지 않은 정점과 연결된 간선만 최소 비용 간선으로 채택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 3번에서 구한 정점과의 최소 비용 간선을 구하는 과정을 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+&amp;nbsp; 3번, 4번 과정을 반복하는 과정을 하려면 PriorityQueue로 구현하는 것이 좋다.&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;blockquote data-ke-style=&quot;style2&quot;&gt;프림 노드&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720706387553&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.prim;

public class PrimNode implements Comparable&amp;lt;PrimNode&amp;gt;{

    int v;
    int weight;

    public PrimNode(int v, int weight) {
        this.v = v;
        this.weight = weight;
    }

    @Override
    public int compareTo(PrimNode o) {
        return this.weight - o.weight;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 크루스칼은 간선의 비용을 기준으로 정렬하기 때문에 u, v 정보가 모두 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프림은 다음 정점까지의 비용을 기준으로 정렬하기 때문에 u 정보가 필요 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Prim Algorithm&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720706570766&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.prim;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;

public class Prim {

    private List&amp;lt;PrimNode&amp;gt;[] graph;
    private List&amp;lt;Integer&amp;gt; path;
    private boolean[] visited;
    private int minimumDistance;

    public Prim(int size) {
        this.graph = new List[size + 1];
        this.path = new ArrayList&amp;lt;&amp;gt;();
        this.visited = new boolean[size + 1];
        this.minimumDistance = Integer.MAX_VALUE;
        initGraph(size);
    }

    private void initGraph(int size) {
        for (int i = 0; i &amp;lt;= size; i++) {
            this.graph[i] = new ArrayList&amp;lt;&amp;gt;();
        }
    }

    public void add(int u, int v, int w) {
        this.graph[u].add(new PrimNode(v, w));
        this.graph[v].add(new PrimNode(u, w));
    }

    public void update(int start) {
        Arrays.fill(visited, false);
        path.clear();
        this.minimumDistance = 0;

        PriorityQueue&amp;lt;PrimNode&amp;gt; pq = new PriorityQueue&amp;lt;&amp;gt;();
        pq.offer(new PrimNode(start, 0));

        while(!pq.isEmpty()) {
            PrimNode node = pq.poll();

            if (visited[node.v]) continue;
            visited[node.v] = true;
            this.minimumDistance += node.weight;
            path.add(node.v);

            for (PrimNode next: graph[node.v]) {
                if (!visited[next.v]) {
                    pq.offer(next);
                }
            }
        }
    }

    public int getMinimumDistance() {
        return this.minimumDistance;
    }

    public void printTrace() {
        for (int v: path) {
            System.out.print(v + &quot; &quot;);
        }
        System.out.println();
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Path는 방문하지 않은 정점 순서대로 최소 비용으로 채택될테니 List 를 통해 추가하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Main&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720706605475&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph.mst.prim;

import com.study.datastructrue.graph.mst.kruskal.PriorityQueueKruskal;

public class Main {

    public static void main(String[] args) {
        Prim prim = new Prim(5);
        prim.add(1, 2, 6);      prim.add(1, 3, 3);
        prim.add(1, 4, 1);      prim.add(2, 5, 4);
        prim.add(3, 4, 2);      prim.add(3, 5, 5);
        prim.add(4, 5, 7);      prim.update(1);

        System.out.println(prim.getMinimumDistance());
        prim.printTrace();
    }

}&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;p data-ke-size=&quot;size16&quot;&gt;정점이 많은 경우, 정점을 기준으로 정렬하는 프림을 사용하면 효율적이겠다.&lt;/p&gt;</description>
      <category>알고리즘/알고리즘 종류</category>
      <category>Graph</category>
      <category>java algorithm 자바 알고리즘</category>
      <category>java data structure 자바 자료구조</category>
      <category>Kruskal</category>
      <category>Minimum Spanning Tree</category>
      <category>MST</category>
      <category>Prim</category>
      <category>최소 신장 트리</category>
      <category>크루스칼</category>
      <category>프림</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/74</guid>
      <comments>https://dev-dot.tistory.com/entry/MST-%EC%B5%9C%EC%86%8C-%EC%8A%A4%ED%8C%A8%EB%8B%9D-%ED%8A%B8%EB%A6%AC-%ED%81%AC%EB%A3%A8%EC%8A%A4%EC%B9%BCKruskal-%ED%94%84%EB%A6%BCPrim#entry74comment</comments>
      <pubDate>Thu, 11 Jul 2024 23:11:34 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Graph (Adjacency Matrix, Adjacency List)</title>
      <link>https://dev-dot.tistory.com/entry/Java-Graph-Adjacency-Matrix-Adjacency-List</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정점(Vertex)과 간선(Edge)로 구성된 것, Graph(G) = (Vertex(V), Edge(E))&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Graph 용어&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정점(Vertex) - 노드, 특정할 수 있는 실체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간선(Edge) - 정점 간 이어져 있는 선&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가중치(Weight) - 정점 간에 거리, 비용 (간선의 길이라고 생각해도 좋음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경로(Path) - 출발 정점에서 도착 정점까지의 거쳐 간 순서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환(Cycle) - 경로의 출발 정점과 도착 정점이 같은 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차수(Degree) - 정점에 붙은 간선 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진입 차수(In-Degree) - 정점으로 들어오는 간선 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진출 차수(Out-Degree) - 정점에서 나가는 간선 수&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Graph 종류&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유향 그래프(Directed Graph) - 특정 정점에서 특정 정점으로 이동하는 그래프&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무향 그래프(UnDirected Graph) - 특정 정점과 특정 정점이 연결된 그래프 (양방향 이동 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가중 그래프(Weighted Graph) - 간선에 가중치(Weight)가 붙음 (유향, 무향으로 표현가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비순환 그래프(Acyclic Graph) - 순환이 없는 그래프&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부분 그래프(Sub Graph) - 특정 그래프 내에 존재하는 그래프&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단절 그래프(Disconnection Graph) - 모든 정점이 연결되어 있지 않은 그래프 (여러 그래프가 존재 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Tip&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 보통 유향 그래프 또는 무향 그래프이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 무향 그래프의 경우 A - B 두 정점간에 사이클로 인식할 수 있으므로 방문처리 필수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 각 그래프를 조합해서 특정 성질을 띠는 그래프 생성가능 ex) 유향 비순환 그래프 (DAG)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 단절 그래프는 알고리즘 문제에서 까먹기 쉬운 성질이다. (보통 Connection Graph로 생각함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;구현 (인접 행렬 방식과 인접 리스트 방식)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;인접 행렬(Adjacency Matrix)&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph;

public class AdjacencyMatrix {
    private int[][] directedGraph;
    private int[][] unDirectedGraph;

    public AdjacencyMatrix(int size) {
       this.directedGraph = new int[size][size];
       this.unDirectedGraph = new int[size][size];
    }

    public void dirAdd(int u, int v) {
       directedGraph[u][v] = 1;
    }

    public void dirAdd(int u, int v, int w) {
       directedGraph[u][v] = w;
    }

    public void dirPrint() {
       for (int i = 0; i &amp;lt; directedGraph.length; i++) {
          System.out.print((char)(i + 'A'));
          for (int j = 0; j &amp;lt; directedGraph[0].length; j++) {
             System.out.printf(&quot;%2d&quot;, directedGraph[i][j]);
          }
          System.out.println();
       }
    }

    public void unDirAdd(int u, int v) {
       unDirectedGraph[u][v] = unDirectedGraph[v][u] = 1;
    }

    public void unDirAdd(int u, int v, int w) {
       unDirectedGraph[u][v] = unDirectedGraph[v][u] = w;
    }

    public void unDirPrint() {
       for (int i = 0; i &amp;lt; unDirectedGraph.length; i++) {
          System.out.print((char)(i + 'A'));
          for (int j = 0; j &amp;lt; unDirectedGraph[0].length; j++) {
             System.out.printf(&quot;%2d&quot;, unDirectedGraph[i][j]);
          }
          System.out.println();
       }
    }

}
&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;size18&quot;&gt;&lt;b&gt;인접 리스트(Adjacency List)&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph;

import java.util.ArrayList;
import java.util.Objects;

public class AdjacnecyList {

    private ArrayList&amp;lt;ArrayList&amp;lt;Object&amp;gt;&amp;gt; directedGraph = new ArrayList&amp;lt;&amp;gt;();
    private ArrayList&amp;lt;ArrayList&amp;lt;Object&amp;gt;&amp;gt; unDirectedGraph = new ArrayList&amp;lt;&amp;gt;();

    public AdjacnecyList(int size) {
       for (int i = 0; i &amp;lt;= size; i++) {
          directedGraph.add(new ArrayList&amp;lt;&amp;gt;());
          unDirectedGraph.add(new ArrayList&amp;lt;&amp;gt;());
       }
    }

    public void dirAdd(int u, int v) {
       directedGraph.get(u).add(v);
    }

    public void dirAdd(int u, int v, int w) {
       directedGraph.get(u).add(new Edge(v, w));
    }

    public void dirPrint() {
       for (int i = 0; i &amp;lt; directedGraph.size(); i++) {
          System.out.print((char)(i + 'A') + &quot;: &quot;);
          for (Object obj : directedGraph.get(i)) {
             if (obj instanceof Integer) {
                System.out.print((char)((int)obj + 'A'));
             } else if (obj instanceof Edge) {
                Edge edge = (Edge) obj;
                System.out.print(&quot;{&quot; + (char)(edge.vertex + 'A') + &quot;, &quot; + edge.weight + &quot;}&quot;);
             }
             System.out.print(&quot; -&amp;gt; &quot;);
          }
          System.out.println();
       }
    }

    public void unDirAdd(int u, int v) {
       unDirectedGraph.get(u).add(v);
       unDirectedGraph.get(v).add(u);
    }

    public void unDirAdd(int u, int v, int w) {
       directedGraph.get(u).add(new Edge(v, w));
       directedGraph.get(v).add(new Edge(u, w));
    }

    public void unDirPrint() {
       for (int i = 0; i &amp;lt; unDirectedGraph.size(); i++) {
          System.out.print((char)(i + 'A') + &quot;: &quot;);
          for (Object obj : unDirectedGraph.get(i)) {
             if (obj instanceof Integer) {
                System.out.print((char)((int)obj + 'A'));
             } else if (obj instanceof Edge) {
                Edge edge = (Edge) obj;
                System.out.print(&quot;{&quot; + (char)(edge.vertex + 'A') + &quot;, &quot; + edge.weight + &quot;}&quot;);
             }
             System.out.print(&quot; -&amp;gt; &quot;);
          }
          System.out.println();
       }
    }
    private class Edge {

       int vertex;
       int weight;

       Edge(int vertex, int weight) {
          this.vertex = vertex;
          this.weight = weight;
       }

    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Main&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;package com.study.datastructrue.graph;

public class Main {

    public static void main(String[] args) {
       AdjacencyMatrix matGraph = new AdjacencyMatrix(5);
       AdjacnecyList listGraph = new AdjacnecyList(5);
       // a -&amp;gt; b, a -&amp;gt; c, a -&amp;gt; d
       // b -&amp;gt; d, d -&amp;gt; e, e -&amp;gt; b
       System.out.println(&quot;Directed Adj Matrix Graph&quot;);
       System.out.println(&quot;  A B C D E&quot;);
       matGraph.dirAdd(0, 1);       matGraph.dirAdd(0, 2);
       matGraph.dirAdd(0, 3);       matGraph.dirAdd(1, 3);
       matGraph.dirAdd(3, 4);       matGraph.dirAdd(4, 1);
       matGraph.dirPrint();

       System.out.println();
       System.out.println(&quot;Directed Adj List Graph&quot;);
       listGraph.dirAdd(0, 1);          listGraph.dirAdd(0, 2);
       listGraph.dirAdd(0, 3);          listGraph.dirAdd(1, 3);
       listGraph.dirAdd(3, 4);          listGraph.dirAdd(4, 1);
       listGraph.dirPrint();

       System.out.println();
       // a - b, a - c, a - d
       // c - d, d - e
       System.out.println(&quot;UnDirected Adj Matrix Graph&quot;);
       System.out.println(&quot;  A B C D E&quot;);
       matGraph.unDirAdd(0, 1);      matGraph.unDirAdd(0, 2);
       matGraph.unDirAdd(0, 3);      matGraph.unDirAdd(2, 3);
       matGraph.unDirAdd(3, 4);
       matGraph.unDirPrint();

       System.out.println();
       System.out.println(&quot;UnDirected Adj List Graph&quot;);
       listGraph.unDirAdd(0, 1);     listGraph.unDirAdd(0, 2);
       listGraph.unDirAdd(0, 3);     listGraph.unDirAdd(2, 3);
       listGraph.unDirAdd(3, 4);
       listGraph.unDirPrint();

    }

}
&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;※ Overloading 으로 인해 dirAdd 또는 unDirAdd 메소드에 Argument를 하나 더 추가하면 가중치가 할당된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nJuvM/btsIsJBW0d0/kUBg5M1nvGn5X2KTYcYX3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nJuvM/btsIsJBW0d0/kUBg5M1nvGn5X2KTYcYX3k/img.png&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;340&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.6889%; margin-right: 10px;&quot; data-widthpercent=&quot;48.25&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nJuvM/btsIsJBW0d0/kUBg5M1nvGn5X2KTYcYX3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnJuvM%2FbtsIsJBW0d0%2FkUBg5M1nvGn5X2KTYcYX3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;229&quot; height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw5HmY/btsItWmGBNf/5gJjXSUr59cgkX7d6Wema0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw5HmY/btsItWmGBNf/5gJjXSUr59cgkX7d6Wema0/img.png&quot; data-origin-width=&quot;242&quot; data-origin-height=&quot;335&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.1483%;&quot; data-widthpercent=&quot;51.75&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw5HmY/btsItWmGBNf/5gJjXSUr59cgkX7d6Wema0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw5HmY%2FbtsItWmGBNf%2F5gJjXSUr59cgkX7d6Wema0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;242&quot; height=&quot;335&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;nbsp;(Directed &amp;amp; UnDirected) &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wxetF/btsIsaGJpmq/DtpJG1CtBHfX3O6unksHG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wxetF/btsIsaGJpmq/DtpJG1CtBHfX3O6unksHG0/img.png&quot; data-origin-width=&quot;273&quot; data-origin-height=&quot;331&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.3128%; margin-right: 10px;&quot; data-widthpercent=&quot;49.89&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wxetF/btsIsaGJpmq/DtpJG1CtBHfX3O6unksHG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwxetF%2FbtsIsaGJpmq%2FDtpJG1CtBHfX3O6unksHG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;273&quot; height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/linR7/btsIsuSxG86/JPnKstFv0TIOXp7VYUhv7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/linR7/btsIsuSxG86/JPnKstFv0TIOXp7VYUhv7k/img.png&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;332&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.5244%;&quot; data-widthpercent=&quot;50.11&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/linR7/btsIsuSxG86/JPnKstFv0TIOXp7VYUhv7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlinR7%2FbtsIsuSxG86%2FJPnKstFv0TIOXp7VYUhv7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;275&quot; height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Weight Graph&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인접행렬 vs 인접리스트&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인접행렬은 두 정점 간에 1번만에 접근할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인접리스트는 두 정점 간에 출발 정점의 간선 개수만에 접근할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인접행렬은 공간을 효율적으로 사용할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인접리스트는 공간을 효율적으로 사용한다.&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;정리 : 인접행렬, 인접리스트 중 구현하기 더 쉬운걸 쓰자. 다만 N &amp;gt; 10,000 인 경우는 무조건 인접리스트!&lt;/p&gt;</description>
      <category>알고리즘/자료구조</category>
      <category>Adjacency List</category>
      <category>adjacency matrix</category>
      <category>Algorithm</category>
      <category>Data structure</category>
      <category>그래프</category>
      <category>알고리즘</category>
      <category>인접리스트</category>
      <category>인접행렬</category>
      <category>자료구조</category>
      <category>자바 백준</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/73</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Graph-Adjacency-Matrix-Adjacency-List#entry73comment</comments>
      <pubDate>Tue, 9 Jul 2024 22:22:54 +0900</pubDate>
    </item>
    <item>
      <title>백준 - [BOJ 22856] 트리 순회</title>
      <link>https://dev-dot.tistory.com/entry/%EB%B0%B1%EC%A4%80-BOJ-22856-%ED%8A%B8%EB%A6%AC-%EC%88%9C%ED%9A%8C</link>
      <description>&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #585f69;&quot;&gt;문제&lt;/span&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div id=&quot;problem_output&quot;&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div id=&quot;problem_description&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;노드가 &lt;span aria-hidden=&quot;true&quot;&gt;N&lt;/span&gt;개인 이진 트리&lt;/span&gt;가 있다. 트리를 중위 순회와 유사하게 순회하려고 한다. 이를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유사 중위 순회&lt;/b&gt;라고 하자.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;순회의 시작은 트리의 루트이고 순회의 끝은 중위 순회할 때 마지막 노드이다. 이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;루트 노드는 항상 1번 노드&lt;/span&gt;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;유사 중위 순회는 루트 노드에서 시작하며, 다음과 같이 진행된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #555555;&quot;&gt;현재 위치한 노드의 왼쪽 자식 노드가 존재하고 아직 방문하지 않았다면, 왼쪽 자식 노드로 이동한다.&lt;/li&gt;
&lt;li style=&quot;color: #555555;&quot;&gt;그렇지 않고 현재 위치한 노드의 오른쪽 자식 노드가 존재하고 아직 방문하지 않았다면, 오른쪽 자식 노드로 이동한다.&lt;/li&gt;
&lt;li style=&quot;color: #555555;&quot;&gt;그렇지 않고 현재 노드가 유사 중위 순회의 끝이라면, 유사 중위 순회를 종료한다.&lt;/li&gt;
&lt;li style=&quot;color: #555555;&quot;&gt;그렇지 않고 부모 노드가 존재한다면, 부모 노드로 이동한다.&lt;/li&gt;
&lt;li style=&quot;color: #555555;&quot;&gt;유사 중위 순회를 종료할 때까지 1 ~ 4를 반복한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;572&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bawkAU/btsIrfNrNBg/dRyUWJtkVfcip4izNU3b5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bawkAU/btsIrfNrNBg/dRyUWJtkVfcip4izNU3b5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bawkAU/btsIrfNrNBg/dRyUWJtkVfcip4izNU3b5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbawkAU%2FbtsIrfNrNBg%2FdRyUWJtkVfcip4izNU3b5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;404&quot; data-origin-width=&quot;572&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 그림에 있는 트리에서 중위 순회를 한다면 4&amp;rarr;2&amp;rarr;5&amp;rarr;1&amp;rarr;6&amp;rarr;3&amp;rarr;7 순으로 순회를 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;유사 중위 순회의 끝&lt;/b&gt;&lt;/span&gt;은 노드 7이 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유사 중위 순회&lt;/b&gt;는 위 그림과 같이 루트인 노드&lt;span&gt;&amp;nbsp;&lt;/span&gt;1에서 시작하여 노드&lt;span&gt;&amp;nbsp;&lt;/span&gt;7에서 끝나고 1&amp;rarr;2&amp;rarr;4&amp;rarr;2&amp;rarr;5&amp;rarr;2&amp;rarr;1&amp;rarr;3&amp;rarr;6&amp;rarr;3&amp;rarr;7&lt;span&gt;&amp;nbsp;&lt;/span&gt;이와 같은 순서로 순회를&amp;nbsp;진행한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유사 중위 순회&lt;/b&gt;를 진행하면서 총 10번 이동하였다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 이동이라는 것은 하나의 노드에서 다른 노드로 한번 움직이는 것을 의미한다. 예를 들면, 노드 1에서 노드 2로 가는 것을 한번 이동하였다고 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유사 중위 순회&lt;/b&gt;를 하면서 이동한 횟수를 구하려고 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;h2 style=&quot;color: #585f69;&quot; data-ke-size=&quot;size26&quot;&gt;입력&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&quot;problem_input&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 줄에 트리를 구성하는 노드의 개수&lt;span&gt; &lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;N&lt;/span&gt;이 주어진다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 줄부터&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;N + 1&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;번째 줄까지 현재 노드 &lt;span aria-hidden=&quot;true&quot;&gt;a,&lt;/span&gt;&amp;nbsp;현재 노드의 왼쪽 자식 노드&lt;span&gt; &lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;b&lt;/span&gt;, 현재 노드의 오른쪽 자식 노드 &lt;span aria-hidden=&quot;true&quot;&gt;c&lt;/span&gt;가 공백으로 구분되어 주어진다.&amp;nbsp;만약 자식 노드의 번호가 -1인 경우 자식 노드가 없다는 것을 의미한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;h2 style=&quot;color: #585f69;&quot; data-ke-size=&quot;size26&quot;&gt;출력&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;유사 중위 순회를 하면서 이동한 총 횟수를 출력한다.&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;해당 문제를 보면 Tree 문제라고 친절하게 알려주고 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;추가적으로, 중위순회와 연관된 문제라고 친절하게 알려주고 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;※ 중위 순위의 특성 맨마지막 노드는 트리의 오른쪽 맨마지막 노드이다.&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번 문제는 이 특성을 가지고 한 번 해결해보려고 한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;private static void pseudoInorder(ArrayList&amp;lt;Node&amp;gt; tree, int node) throws IOException {
    if (tree.get(node).left != -1) {
       CNT++;
       pseudoInorder(tree, tree.get(node).left);
       CNT++;
    }
    if (tree.get(node).right != -1) {
       CNT++;
       pseudoInorder(tree, tree.get(node).right);
       CNT++;
    }
}&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;우선 유사 중위 순회를 한다. 왼쪽 노드로 이동하면서 Count++, 왼쪽 노드에서 돌아오면서 Count++ 되는 로직을 그대로 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;vbscript&quot;&gt;&lt;code&gt;for (int i = 1; tree.get(i).right != -1; i=tree.get(i).right) {
    RIGHT_NODE_COUNT++;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;BW.write(String.valueOf(CNT - RIGHT_NODE_COUNT));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 두 값을 빼준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720366776984&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.*;


class Node {

	int left;
	int right;

	public Node() {
	}

}

public class Main {

	static BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
	static int N;
	static int RIGHT_NODE_COUNT = 0;
	static int CNT = 0;

	public static void main(String[] args) throws IOException {
		StringTokenizer st = new StringTokenizer(BR.readLine());
		N = Integer.parseInt(st.nextToken());

		ArrayList&amp;lt;Node&amp;gt; tree = new ArrayList&amp;lt;&amp;gt;();
		for (int i = 0; i &amp;lt;= N; i++) {
			tree.add(new Node());
		}

		for (int i = 0; i &amp;lt; N; i++) {
			st = new StringTokenizer(BR.readLine());
			int node = Integer.parseInt(st.nextToken());
			tree.get(node).left = Integer.parseInt(st.nextToken());
			tree.get(node).right = Integer.parseInt(st.nextToken());
		}

		for (int i = 1; tree.get(i).right != -1; i=tree.get(i).right) {
			RIGHT_NODE_COUNT++;
		}

		pseudoInorder(tree, 1);

		BW.write(String.valueOf(CNT - RIGHT_NODE_COUNT));
		BW.flush();
		BR.close();
		BW.close();
	}

	private static void pseudoInorder(ArrayList&amp;lt;Node&amp;gt; tree, int node) throws IOException {
		if (tree.get(node).left != -1) {
			CNT++;
			pseudoInorder(tree, tree.get(node).left);
			CNT++;
		}
		if (tree.get(node).right != -1) {
			CNT++;
			pseudoInorder(tree, tree.get(node).right);
			CNT++;
		}
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;TIP&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package com.study.algorithm.boj22856;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {

    static BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    static int N;
    static int RIGHT_NODE_COUNT = 0;

    public static void main(String[] args) throws IOException {
       StringTokenizer st = new StringTokenizer(BR.readLine());
       N = Integer.parseInt(st.nextToken());

       int tree[][] = new int[N+1][2];

       for (int i = 0; i &amp;lt; N; i++) {
          st = new StringTokenizer(BR.readLine());
          int node = Integer.parseInt(st.nextToken());
          tree[node][0] = Integer.parseInt(st.nextToken());
          tree[node][1] = Integer.parseInt(st.nextToken());
       }

       for (int i = 1; tree[i][1] != -1; i=tree[i][1]) {
          RIGHT_NODE_COUNT++;
       }

       BW.write(String.valueOf((N - 1) * 2 - RIGHT_NODE_COUNT));
       BW.flush();
       BR.close();
       BW.close();
    }

}&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;Tree의 특성을 이용하면 더 쉽다. Inorder는 모든 Node를 다 방문하므로 Edge의 개수 (N-1) 만큼 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pseudo Inorder를 하면서 2번씩 진행하므로 (N - 1) * 2 번 씩 방문하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Inorder 결과인 오른쪽 노드까지의 엣지수를 빼준다.&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;결과 : (N - 1) * 2 - RIGHT_NODE_COUNT 로 구할 수 있다.&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>Algorithm</category>
      <category>boj 22856</category>
      <category>CS</category>
      <category>Graph</category>
      <category>java</category>
      <category>tree</category>
      <category>백준 22856</category>
      <category>백준 풀이</category>
      <category>알고리즘 트리 순회</category>
      <category>트리 순회</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/72</guid>
      <comments>https://dev-dot.tistory.com/entry/%EB%B0%B1%EC%A4%80-BOJ-22856-%ED%8A%B8%EB%A6%AC-%EC%88%9C%ED%9A%8C#entry72comment</comments>
      <pubDate>Mon, 8 Jul 2024 00:43:10 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Binary Tree</title>
      <link>https://dev-dot.tistory.com/entry/Java-Binary-Tree</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Binary Tree는 트리를 통해 데이터를 비선형적으로 관리하는 자료구조이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 포스팅에서 BST(Binary Search Tree)에 대해서 설명했는데 BST도 이진 트리를 기반한 자료구조이다.&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;왜 Binary Tree를 사용할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tree Post에서도 설명했는데 일반 DAG와 같은 Tree는 효율성 측면에서 너무 부족하다. 그저 Graph와 다름이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 실제 데이터 처리를 하기 위해 Binary Tree로 효율성을 극대화하는 방법을 채택한 것이다.&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;크게 Binary Tree의 두 종류를 알아보자.&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. 완전 이진 트리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 편향 트리&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 많지만 Binary Tree의 핵심을 설명하기에 두 가지가 최고인 것 같다.&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;위 두가지 개념을 언급한 이유는 BST의 문제점 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 작성한 BST 코드에서 작은 값은 왼쪽, 큰 값은 오른쪽에서 sub tree를 생성하면서 잘 정리가 되어있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;260&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rYOVM/btsIqQ1pZ5M/PiLBecrb2Iy39QtZzoQh71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rYOVM/btsIqQ1pZ5M/PiLBecrb2Iy39QtZzoQh71/img.png&quot; data-alt=&quot;편향트리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rYOVM/btsIqQ1pZ5M/PiLBecrb2Iy39QtZzoQh71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrYOVM%2FbtsIqQ1pZ5M%2FPiLBecrb2Iy39QtZzoQh71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;260&quot; height=&quot;155&quot; data-origin-width=&quot;260&quot; data-origin-height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;편향트리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 그림처럼 오름차순으로만 데이터를 입력한다면? 편향트리가 발생한다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 100만개가 오름차순일 때, Log_2(100만) 에서 선형탐색으로 바뀐다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약 50,000만 배 느려진다. 물론 데이터가 더 많아질수록 더 느려질 것이다. 이런 문제가 BST에서 발생한다는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YwwT6/btsIrx1mKIf/DF9vEBk15bVkTk51f4oRF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YwwT6/btsIrx1mKIf/DF9vEBk15bVkTk51f4oRF1/img.png&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;156&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.696%; margin-right: 10px;&quot; data-widthpercent=&quot;46.23&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YwwT6/btsIrx1mKIf/DF9vEBk15bVkTk51f4oRF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYwwT6%2FbtsIrx1mKIf%2FDF9vEBk15bVkTk51f4oRF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;128&quot; height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dp6GcC/btsIqUQiJxQ/5ukoCXfB7s3xRmgJWsUNFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dp6GcC/btsIqUQiJxQ/5ukoCXfB7s3xRmgJWsUNFk/img.png&quot; data-origin-width=&quot;125&quot; data-origin-height=&quot;131&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.1412%;&quot; data-widthpercent=&quot;53.77&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dp6GcC/btsIqUQiJxQ/5ukoCXfB7s3xRmgJWsUNFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdp6GcC%2FbtsIqUQiJxQ%2F5ukoCXfB7s3xRmgJWsUNFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;125&quot; height=&quot;131&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 이것을 해결하기 위한 방법 중 하나가 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;완전&lt;span&gt; &lt;/span&gt;&lt;/span&gt;이진트리를 유지하는 것인데 왼쪽 사진에서 4를 지웠더니 완전 이진트리가 유지되지 않고 있다는 것이다. 이것을 해결하는 방법이 자가균형트리 (Self-Balancing Tree) 이며 대표적으로 Red-Black Tree, AVL Tree가 존재한다.&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;이 자가균형 트리를 이용한 것이 Java의 TreeSet과 TreeMap 인데 시간이 되면 한 번 작성해보자...&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;번외로 Binary Tree에는 문자열 검색을 위한 Trie, 최솟값과 최댓값 검색에 효율적인 Heap이라는 자료구조 또한 존재한다.&lt;/p&gt;</description>
      <category>알고리즘/자료구조</category>
      <category>binray tree</category>
      <category>BST</category>
      <category>CS</category>
      <category>tree</category>
      <category>백준</category>
      <category>자가균형 트리</category>
      <category>자바 알고리즘</category>
      <category>자바 자료구조</category>
      <category>컴퓨터 공학</category>
      <category>프로그래머스</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/71</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Binary-Tree#entry71comment</comments>
      <pubDate>Mon, 8 Jul 2024 00:28:33 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Binary Search Tree</title>
      <link>https://dev-dot.tistory.com/entry/Java-Binary-Search-Tree</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;앞 포스팅에서 작성한 Tree의 비효율적인 문제를 개선하기 위해 생긴 이진 탐색 트리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 여러 자식을 가질 수 있지만 이진 검색 트리에서는 Binary Tree의 개념을 사용하기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식이 Left, Right만 존재한다. 이를 통해 Log_2 (N) 번만에 모든 수행을 끝낼 수 있다.&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;또, inorder를 수행 시 오름차순 정렬된 결과를 얻을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.binarysearchtree;

public class Node {
    int value;
    Node left;
    Node right;

    public Node(int value) {
       this.value = value;
       left = null;
       right = null;
    }
}
&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.binarysearchtree;

public class LinkedListBST {
    private Node root;
    private int size;

    public LinkedListBST() {
       this.root = null;
       this.size = 0;
    }

    public void add(int value) {
       this.root = addRecursive(root, value);
       this.size++;
    }

    private Node addRecursive(Node current, int value) {
       if (current == null) {
          return new Node(value);
       }

       if (value &amp;lt; current.value) {
          current.left = addRecursive(current.left, value);
       } else if (value &amp;gt; current.value) {
          current.right = addRecursive(current.right, value);
       }

       return current;
    }

    public boolean delete(int value) {
       int originalSize = size;
       this.root = deleteRecursive(root, value);
       return size &amp;lt; originalSize;
    }

    private Node deleteRecursive(Node current, int value) {
       if (current == null) {
          return null;
       }

       if (value == current.value) {
          if (current.left == null &amp;amp;&amp;amp; current.right == null) {
             size--;
             return null;
          }

          if (current.left == null) {
             size--;
             return current.right;
          }

          if (current.right == null) {
             size--;
             return current.left;
          }

          int smallestValue = findSmallestValue(current.right);
          current.value = smallestValue;
          current.right = deleteRecursive(current.right, smallestValue);
          return current;
       }

       if (value &amp;lt; current.value) {
          current.left = deleteRecursive(current.left, value);
          return current;
       }

       current.right = deleteRecursive(current.right, value);
       return current;
    }

    private int findSmallestValue(Node root) {
       return root.left == null ? root.value : findSmallestValue(root.left);
    }

    public void printTree() {
       printTree(root, 0);
    }

    private void printTree(Node node, int level) {
       if (node == null) {
          return;
       }

       printTree(node.right, level + 1);

       if (level != 0) {
          for (int i = 0; i &amp;lt; level - 1; i++) {
             System.out.print(&quot;|\t&quot;);
          }
          System.out.println(&quot;|-------&quot; + node.value);
       } else {
          System.out.println(node.value);
       }

       printTree(node.left, level + 1);
    }

    public void traverseInOrder() {
       traverseInOrder(root);
       System.out.println();
    }

    private void traverseInOrder(Node node) {
       if (node != null) {
          traverseInOrder(node.left);
          System.out.print(&quot; &quot; + node.value);
          traverseInOrder(node.right);
       }
    }

    public void traversePreOrder() {
       traversePreOrder(root);
       System.out.println();
    }
    private void traversePreOrder(Node node) {
       if (node != null) {
          System.out.print(&quot; &quot; + node.value);
          traversePreOrder(node.left);
          traversePreOrder(node.right);
       }
    }
    public void traversePostOrder() {
       traversePostOrder(root);
       System.out.println();
    }
    private void traversePostOrder(Node node) {
       if (node != null) {
          traversePostOrder(node.left);
          traversePostOrder(node.right);
          System.out.print(&quot; &quot; + node.value);
       }
    }

    public int size() {
       return size;
    }

}
&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;1. 작은 값은 왼쪽 자식으로 큰 값은 오른쪽 자식으로 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( 중복된 값을 허용할 경우, count를 사용하거나 여러 방법이 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 삭제 시 고려할 점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 삭제할 값을 찾았을 경우,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 자식이 존재하지 않는다면 내가 지워진 것이니 null을 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 왼쪽 자식이 존재하지 않는다면 오른쪽 자식을 반환해주어서 Level을 맞춤.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) 오른쪽 자식이 존재하지 않는다면 왼쪽 자식을 반환해주어서 Level을 맞춤.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) 자식이 둘 다 존재한다면 큰 녀석 중 가장 작은 녀석으로 교체해주어야 함. inorder의 특성을 맞추기 위함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WBxWs/btsIpWVExTM/n6hJoKqQ5P36GpotJzxmE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WBxWs/btsIpWVExTM/n6hJoKqQ5P36GpotJzxmE1/img.png&quot; data-origin-width=&quot;120&quot; data-origin-height=&quot;155&quot; data-is-animation=&quot;false&quot; style=&quot;width: 28.0565%; margin-right: 10px;&quot; data-widthpercent=&quot;28.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WBxWs/btsIpWVExTM/n6hJoKqQ5P36GpotJzxmE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWBxWs%2FbtsIpWVExTM%2Fn6hJoKqQ5P36GpotJzxmE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;120&quot; height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pEI6w/btsIqyUfG5F/mCfXFRMlS4HYita5OSkat0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pEI6w/btsIqyUfG5F/mCfXFRMlS4HYita5OSkat0/img.png&quot; data-origin-width=&quot;125&quot; data-origin-height=&quot;64&quot; data-is-animation=&quot;false&quot; style=&quot;width: 70.7807%;&quot; data-widthpercent=&quot;71.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pEI6w/btsIqyUfG5F/mCfXFRMlS4HYita5OSkat0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpEI6w%2FbtsIqyUfG5F%2FmCfXFRMlS4HYita5OSkat0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;125&quot; height=&quot;64&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt; TreePrint 및 PreOrder, InOrder, PostOrder 결과 &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;118&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xU8EH/btsIqSStYSv/sj41RMOrw8h8QHd4shpvok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xU8EH/btsIqSStYSv/sj41RMOrw8h8QHd4shpvok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xU8EH/btsIqSStYSv/sj41RMOrw8h8QHd4shpvok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxU8EH%2FbtsIqSStYSv%2Fsj41RMOrw8h8QHd4shpvok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;118&quot; height=&quot;159&quot; data-origin-width=&quot;118&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4를 지운 후에도 InOrder 결과가 오름차순 인 것을 볼 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.binarysearchtree;

public class ArrayBST {
    private int[] tree;
    private int size;

    public ArrayBST(int capacity) {
       tree = new int[capacity];
       size = 0;

       for (int i = 0; i &amp;lt; capacity; i++) {
          tree[i] = Integer.MIN_VALUE;
       }
    }

    public void add(int value) {
       if (size == 0) {
          tree[0] = value;
          size++;
       } else {
          addRecursive(0, value);
       }
    }

    private void addRecursive(int index, int value) {
       if (tree[index] == Integer.MIN_VALUE) {
          tree[index] = value;
          size++;
       } else if (value &amp;lt; tree[index]) {
          int leftChildIndex = 2 * index + 1;
          addRecursive(leftChildIndex, value);
       } else if (value &amp;gt; tree[index]) {
          int rightChildIndex = 2 * index + 2;
          addRecursive(rightChildIndex, value);
       }
    }
    public void printTree() {
       printTreeRecursive(0, 0);
    }

    private void printTreeRecursive(int index, int level) {
       if (index &amp;gt;= tree.length || tree[index] == Integer.MIN_VALUE) {
          return;
       }
       printTreeRecursive(2 * index + 2, level + 1);

       for (int i = 0; i &amp;lt; level; i++) {
          System.out.print(&quot;    &quot;);
       }
       System.out.println(tree[index]);

       printTreeRecursive(2 * index + 1, level + 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;BST는 LinkedList 뿐만 아니라 Array로도 구현이 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;119&quot; data-origin-height=&quot;149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqYx8m/btsIqOP30KO/tsg2hlrIDY3ymaxKB8kPA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqYx8m/btsIqOP30KO/tsg2hlrIDY3ymaxKB8kPA1/img.png&quot; data-alt=&quot;Array BST 실행결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqYx8m/btsIqOP30KO/tsg2hlrIDY3ymaxKB8kPA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqYx8m%2FbtsIqOP30KO%2Ftsg2hlrIDY3ymaxKB8kPA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;119&quot; height=&quot;149&quot; data-origin-width=&quot;119&quot; data-origin-height=&quot;149&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Array BST 실행결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.binarysearchtree;

import java.util.TreeSet;

public class Main {

    public static void main(String[] args) {
       LinkedListBST bt = new LinkedListBST();

       bt.add(6);
       bt.add(4);
       bt.add(8);
       bt.add(3);
       bt.add(5);
       bt.add(7);
       bt.add(9);

       bt.printTree();
       bt.traversePreOrder();
       bt.traverseInOrder();
       bt.traversePostOrder();

       bt.delete(4);
       bt.printTree();
       bt.traverseInOrder();

       ArrayBST bst = new ArrayBST(10);
       bst.add(6);
       bst.add(4);
       bst.add(8);
       bst.add(3);
       bst.add(5);
       bst.add(7);
       bst.add(9);
       bst.printTree();
    }

}
&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;Java에서는 Tree를 구현해 둔 것이 있는데 바로 TreeSet 과 TreeMap 이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Java의 Tree는 Red-Black Tree로 자가균형트리라고도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 이진 트리 종류 중 균형트리라는 자료구조 중 하나인데 다음 포스트에 설명하겠다.&lt;/p&gt;</description>
      <category>알고리즘/자료구조</category>
      <category>BST</category>
      <category>Data structure</category>
      <category>tree</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>이진검색트리</category>
      <category>이진탐색</category>
      <category>자료구조</category>
      <category>자바 알고리즘</category>
      <category>자바 자료구조</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/70</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Binary-Search-Tree#entry70comment</comments>
      <pubDate>Mon, 8 Jul 2024 00:08:31 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Tree</title>
      <link>https://dev-dot.tistory.com/entry/Java-Tree</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;트리 자료구조의 종류 : Tree, Binary Tree, Binary Serach Tree, Balanced Binary Serach Tree, Heap, Trie&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스트에서는 기본적인 Tree에 대해서만 작성해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Tree란 ?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node와 Edge로 구성된 &lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;방향이 존재하는 비순환&lt;/span&gt; Graph의 한 종류이다. 그래서&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;DAG(Directed Acyclic Graphs)라고도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 Graph로 분류하면 되지 왜 Tree냐는 의심을 하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tree는 Graph에서 몇가지 특성을 더 가진다.&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. 루트 노드가 하나 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 부모 노드는 하나밖에 존재하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 노드는 0개 이상의 자식을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 자식이 0개인 경우 단말노드(Leaf Node)라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.. 위 특성을 지키는 트리의 경우 엣지가 N-1개이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 엣지가 N-1개 이므로 두 정점간 경로는 1가지이다.&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.tree;

import java.util.ArrayList;

public class Node&amp;lt;T&amp;gt; {
    private T data;
    private ArrayList&amp;lt;Node&amp;gt; children;

    public Node(final T data) {
       this.data = data;
       this.children = new ArrayList&amp;lt;&amp;gt;();
    }

    public T getData() {
       return data;
    }

    public void setData(final T data) {
       this.data = data;
    }

    public ArrayList&amp;lt;Node&amp;gt; getChildren() {
       return children;
    }

    public void add(Node data) {
       children.add(data);
    }

}
&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;p data-ke-size=&quot;size16&quot;&gt;트리는 DAG라고 했으므로 자식이 여러개 일 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.tree;

import java.util.ArrayList;

public class MyTree&amp;lt;T&amp;gt; {

    private Node&amp;lt;T&amp;gt; root;

    public MyTree() {
       this.root = null;
    }

    public void add(T to, T data) {
       if (this.root == null) {
          this.root = new Node(data);
          return ;
       }
       final Node node = findFirst(to);
       if (node == null) {
          throw new IllegalArgumentException(&quot;NOT Found Node&quot;);
       }
       node.add(new Node(data));
    }

    public Node findFirst(T data) {
       if (root.getData() == data) return root;
       return findFirst(root, data);
    }

    private Node findFirst(Node&amp;lt;T&amp;gt; cur, T data) {
       for (int i = 0; i &amp;lt; cur.getChildren().size(); i++) {
          if (cur.getChildren().get(i).getData() == data) {
             return cur.getChildren().get(i);
          }
       }
       for (Node node : root.getChildren()) {
          return findFirst(node, data);
       }
       return null;
    }

    public void printTree() {
       ArrayList&amp;lt;StringBuilder&amp;gt; sbs = new ArrayList&amp;lt;&amp;gt;();
       final int depth = depth(root, 0);
       for (int i = 0; i &amp;lt;= depth; i++) {
          sbs.add(new StringBuilder());
       }
       printTree(root, 0, sbs);
       for (StringBuilder sb: sbs) {
          System.out.println(sb.toString());
       }
    }

    private int depth(Node&amp;lt;T&amp;gt; cur, int level) {
       int maxLevel = level;
       for (int i = 0; i &amp;lt; cur.getChildren().size(); i++) {
          maxLevel = Math.max(depth(cur.getChildren().get(i), level + 1), maxLevel);
       }
       return maxLevel;
    }

    private void printTree(Node&amp;lt;T&amp;gt; cur, int level, final ArrayList&amp;lt;StringBuilder&amp;gt; sbs) {
       StringBuilder sb = sbs.get(level);
       sb.append(cur.getData() + &quot; &quot;);
       for (int i = 0; i &amp;lt; cur.getChildren().size(); i++) {
          printTree(cur.getChildren().get(i), level + 1, sbs);
       }
       sb.append(&quot;|&quot;);

    }


}
&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;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;이런 비효율적인 문제를 개선하기 위해 이진 탐색 트리(Binary Search Tree)라는 것이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기준 값보다 작은 값은 왼쪽에 큰 값은 오른쪽에 비선형적, 계층적으로 저장해서 Log_2 N번만에 검색하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 삼진, 사진으로 나누면 더 빠르게 검색할 수 있는 것 아닌가? 라는 생각이 들었는데 실제로 DB에서 사용하고 있다. 이 부분은 나중에 작성.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;package com.study.datastructrue.nonlinear.tree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class Main {

    public static void main(String[] args) {
       // 복잡한 트리 설계
       MyTree&amp;lt;Integer&amp;gt; tree = new MyTree&amp;lt;&amp;gt;();

       tree.add(0, 1);
       tree.add(1, 2);
       tree.add(2, 3);
       tree.add(2, 4);
       tree.add(2, 5);

       tree.printTree();

       // PS용 간단한 ADJ 트리 설계
       int vertexCount = 10;
       int level[] = new int[vertexCount + 1];
       ArrayList&amp;lt;ArrayList&amp;lt;Integer&amp;gt;&amp;gt; tree2 = new ArrayList&amp;lt;&amp;gt;();
       ArrayList&amp;lt;StringBuilder&amp;gt; sbs = new ArrayList&amp;lt;&amp;gt;();
       for (int i = 0; i &amp;lt;= vertexCount; i++) {
          sbs.add(new StringBuilder());
          tree2.add(new ArrayList&amp;lt;&amp;gt;());
       }
       tree2.get(1).add(2);
       tree2.get(2).add(3);
       tree2.get(2).add(4);
       tree2.get(2).add(5);
       Queue&amp;lt;Integer&amp;gt; q = new LinkedList&amp;lt;&amp;gt;();
       q.add(1);  level[1] = 1;  sbs.get(1).append(1);
       int maxLevel = 1;
       // BFS
       while (!q.isEmpty()) {
          int x = q.poll();
          maxLevel = Math.max(maxLevel, level[x]);
          for (int i : tree2.get(x)) {
             level[i] = level[x] + 1;
             sbs.get(level[i]).append(i + &quot; &quot;);
             q.add(i);
          }
       }
       for (int i = 1; i &amp;lt;= maxLevel; i++) {
          System.out.println(sbs.get(i).toString());
       }
    }

}
&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;Graph에 가까운 Tree 사용과 PS 용으로 짧게 사용할 수 있는 코드&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/자료구조</category>
      <category>dag</category>
      <category>Data structure</category>
      <category>Graph</category>
      <category>tree</category>
      <category>노드</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자료구조</category>
      <category>자바</category>
      <category>트리</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/69</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Tree#entry69comment</comments>
      <pubDate>Sun, 7 Jul 2024 23:02:09 +0900</pubDate>
    </item>
    <item>
      <title>백준 - [BOJ 1865] 웜홀</title>
      <link>https://dev-dot.tistory.com/entry/%EB%B0%B1%EC%A4%80-BOJ-1865-%EC%9B%9C%ED%99%80</link>
      <description>&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #585f69;&quot;&gt;문제&lt;/span&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div id=&quot;problem_output&quot;&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div id=&quot;problem_description&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;때는 2020년, 백준이는 월드나라의 한 국민이다. 월드나라에는 N개의 지점이 있고 N개의 지점 사이에는 &lt;span style=&quot;color: #ee2323;&quot;&gt;M개의 도로와 W개의 웜홀&lt;/span&gt;이 있다. (단 도로는 방향이 없으며 웜홀은 방향이 있다.) 웜홀은 시작 위치에서 도착 위치로 가는 하나의 경로인데, 특이하게도 도착을 하게 되면 시작을 하였을 때보다 시간이 뒤로 가게 된다. &lt;span style=&quot;color: #ee2323;&quot;&gt;웜홀 내에서는 시계가 거꾸로 간다고 생각하여도 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;시간 여행을 매우 좋아하는 백준이는 한 가지 궁금증에 빠졌다.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;한&amp;nbsp;지점에서 출발을 하여서 시간여행을 하기 시작하여 다시 출발을 하였던 위치로 돌아왔을 때, 출발을 하였을 때보다 시간이 되돌아가 있는 경우가 있는지 없는지 궁금해졌다&lt;/span&gt;. 여러분은 백준이를 도와 이런 일이 가능한지 불가능한지 구하는 프로그램을 작성하여라.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;h2 style=&quot;color: #585f69;&quot; data-ke-size=&quot;size26&quot;&gt;입력&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&quot;problem_input&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 줄에는 테스트케이스의 개수 TC(1 &amp;le; TC &amp;le; 5)가 주어진다. 그리고 두 번째 줄부터 TC개의 테스트케이스가 차례로 주어지는데 각 테스트케이스의 첫 번째 줄에는 지점의 수 N(1 &amp;le; N &amp;le; 500), 도로의 개수 M(1 &amp;le; M &amp;le; 2500), 웜홀의 개수 W(1 &amp;le; W &amp;le; 200)이 주어진다. 그리고 두 번째 줄부터 M+1번째 줄에 도로의 정보가 주어지는데 각 도로의 정보는 S, E, T 세 정수로 주어진다. S와 E는 연결된 지점의 번호, T는 이 도로를 통해 이동하는데 걸리는 시간을 의미한다. 그리고 M+2번째 줄부터 M+W+1번째 줄까지 웜홀의 정보가 S, E, T 세 정수로 주어지는데 S는 시작 지점, E는 도착 지점, T는 줄어드는 시간을 의미한다. T는 10,000보다 작거나 같은 자연수 또는 0이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두 지점을 연결하는 도로가 한 개보다 많을 수도 있다. 지점의 번호는 1부터 N까지 자연수로 중복 없이 매겨져 있다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;h2 style=&quot;color: #585f69;&quot; data-ke-size=&quot;size26&quot;&gt;출력&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&quot;problem_output&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;TC개의 줄에 걸쳐서 만약에 시간이 줄어들면서 출발 위치로 돌아오는 것이 가능하면 YES, 불가능하면 NO를 출력한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨간 글을 보면 벨만포드 알고리즘이라는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 ? 한 지점에서 돌아오다 - Cycle, 시간이 되돌아간다 - 음수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Negative Cycle을 형성하는 것으로 벨만포드 알고리즘을 떠올릴 수 있다.&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;벨만 포드 알고리즘은 O(VE) 이므로 500 * 2700 = 1350000, 충분하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;package com.study.algorithm.boj1865;
import java.io.*;
import java.util.*;

class Pair {
    int e;
    int t;

    Pair(int e, int t) {
        this.e = e;
        this.t = t;
    }

}

public class Main {

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static ArrayList&amp;lt;ArrayList&amp;lt;Pair&amp;gt;&amp;gt; STATIONS;
    static int N, M, W;
    static int INF = (int)1e8;

    public static void main(String[] args) throws IOException {
        StringTokenizer st = new StringTokenizer(br.readLine());
        StringBuilder sb = new StringBuilder();

        int tc = Integer.parseInt(st.nextToken());
        while (tc-- &amp;gt; 0) {
            input();
            //inputDebug();
            sb.append(bellmanFord());
        }
        //inputDebug();
        bw.write(sb.toString());
        bw.close();
        br.close();
    }

    private static String bellmanFord() {
        int dist[] = new int[N + 1];
        Arrays.fill(dist, INF);
        dist[1] = 0;

        for (int loop = 0; loop &amp;lt;= N; loop++) {
            for (int i = 1; i &amp;lt;= N; i++) {
                for (Pair path : STATIONS.get(i)) {
                    if (dist[path.e] &amp;gt; dist[i] + path.t) {
                        if (loop == N) {
                            return &quot;YES\n&quot;;
                        }
                        dist[path.e] = dist[i] + path.t;
                    }
                }
            }
        }

        return &quot;NO\n&quot;;
    }

    private static void input() throws IOException {
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        W = Integer.parseInt(st.nextToken());

        STATIONS = new ArrayList&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt;= N; i++) {
            STATIONS.add(new ArrayList&amp;lt;&amp;gt;());
        }

        int cnt = M + W;
        for (int i = 0; i &amp;lt; cnt; i++) {
            st = new StringTokenizer(br.readLine());
            int s = Integer.parseInt(st.nextToken());
            int e = Integer.parseInt(st.nextToken());
            int t = Integer.parseInt(st.nextToken());

            if (i &amp;lt; M) {
                STATIONS.get(s).add(new Pair(e, t));
                STATIONS.get(e).add(new Pair(s, t));
            } else {
                STATIONS.get(s).add(new Pair(e, -t));
            }
        }
    }
/*
    private static void inputDebug() {
            for (int i = 0; i &amp;lt; STATIONS.size(); i++) {
                for (Pair p : STATIONS.get(i)) {
                    System.out.printf(&quot;%d -&amp;gt; %d : %d\n&quot;, i, p.e, p.t);
                }
            }
    }*/

}
&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;포스트 중 벨만포드 알고리즘에서 설명한 내용처럼 N번째에 최단경로가 업데이트 된다면 음수 사이클이 존재한다고 알 수 있다는 것을 이용해서 해결했다.&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;a href=&quot;https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1720275789034&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[MST] Bellman-Ford Algorithm&quot; data-og-description=&quot;최단경로 알고리즘package com.study.datastructrue.mst;import java.util.ArrayList;import java.util.Arrays;class Pair { T node; V cost; public Pair(T node, V cost) { this.node = node; this.cost = cost; }}public class BellmanFord { static long[] dist =&quot; data-og-host=&quot;dev-dot.tistory.com&quot; data-og-source-url=&quot;https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm&quot; data-og-url=&quot;https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lbfv0/hyWvOopr5h/ZJO6MMkVwvv8tGxqC79KUK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/KHlip/hyWvKffhIF/rPJmGGyUGTrqua8BbFVZlk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lbfv0/hyWvOopr5h/ZJO6MMkVwvv8tGxqC79KUK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/KHlip/hyWvKffhIF/rPJmGGyUGTrqua8BbFVZlk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[MST] Bellman-Ford Algorithm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최단경로 알고리즘package com.study.datastructrue.mst;import java.util.ArrayList;import java.util.Arrays;class Pair { T node; V cost; public Pair(T node, V cost) { this.node = node; this.cost = cost; }}public class BellmanFord { static long[] dist =&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dev-dot.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <category>BOJ 1865</category>
      <category>MST</category>
      <category>PS</category>
      <category>백준 1865</category>
      <category>백준 웜홀</category>
      <category>백준 자바</category>
      <category>벨만포드 알고리즘</category>
      <category>알고리즘</category>
      <category>웜홀</category>
      <category>자바 알고리즘</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/68</guid>
      <comments>https://dev-dot.tistory.com/entry/%EB%B0%B1%EC%A4%80-BOJ-1865-%EC%9B%9C%ED%99%80#entry68comment</comments>
      <pubDate>Sat, 6 Jul 2024 23:25:40 +0900</pubDate>
    </item>
    <item>
      <title>[최단경로] Bellman-Ford Algorithm</title>
      <link>https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최단경로 알고리즘&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package com.study.datastructrue.mst;

import java.util.ArrayList;
import java.util.Arrays;

class Pair&amp;lt;T, V&amp;gt; {

    T node;
    V cost;

    public Pair(T node, V cost) {
        this.node = node;
        this.cost = cost;
    }

}

public class BellmanFord {

    static long[] dist = new long[6];

    public static void main(String[] args) {
        // 집 1, 학교 2, 박물관 3, 영화관 4, 마트 5
        ArrayList&amp;lt;ArrayList&amp;lt;Pair&amp;lt;Integer, Integer&amp;gt;&amp;gt;&amp;gt; graph = input();
        for (int i = 1; i &amp;lt; graph.size(); i++) {
            dist = bellmanFord(graph, i);
            for (long dis: dist) {
                System.out.printf((dis == Integer.MAX_VALUE ? &quot;INF&quot; : dis) + &quot; &quot;);
            }
            System.out.println();
        }

        for (int i = 1; i &amp;lt; graph.size(); i++) {
            for (Pair&amp;lt;Integer, Integer&amp;gt; path : graph.get(i)) {
                if (dist[path.node] &amp;gt; dist[i] + path.cost) {
                    System.out.print(&quot;negative cycle exists ........&quot;);
                }
            }
        }
    }

    public static ArrayList&amp;lt;ArrayList&amp;lt;Pair&amp;lt;Integer, Integer&amp;gt;&amp;gt;&amp;gt; input() {
        ArrayList&amp;lt;ArrayList&amp;lt;Pair&amp;lt;Integer, Integer&amp;gt;&amp;gt;&amp;gt; graph = new ArrayList&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt;= 5; i++) {
            graph.add(new ArrayList&amp;lt;&amp;gt;());
        }

        graph.get(1).add(new Pair&amp;lt;&amp;gt;(2, -1));
        graph.get(1).add(new Pair&amp;lt;&amp;gt;(5, 4));
        graph.get(2).add(new Pair&amp;lt;&amp;gt;(3, 2));
        graph.get(2).add(new Pair&amp;lt;&amp;gt;(4, 1));
        graph.get(2).add(new Pair&amp;lt;&amp;gt;(5, 3));
        graph.get(3).add(new Pair&amp;lt;&amp;gt;(4, -3)); // 음수 값에 따라 음수 사이클 판별 가능
        graph.get(4).add(new Pair&amp;lt;&amp;gt;(2, 2));
        graph.get(4).add(new Pair&amp;lt;&amp;gt;(5, 5));

        return graph;
    }

    public static long[] bellmanFord(
            ArrayList&amp;lt;ArrayList&amp;lt;Pair&amp;lt;Integer, Integer&amp;gt;&amp;gt;&amp;gt; graph,
            int start
    ) {
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[start] = 0;

        for (int node = 0; node &amp;lt; 5; node++) {
            for (int i = 1; i &amp;lt; graph.size(); i++) {
            	if (dist[i] == Integer.MAX_VALUE) continue;
                for (Pair&amp;lt;Integer, Integer&amp;gt; path : graph.get(i)) {
                    if (dist[path.node] &amp;gt; dist[i] + path.cost) {
                        dist[path.node] = dist[i] + path.cost;
                    }
                }
            }
        }

        return dist;
    }

}&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;p data-ke-size=&quot;size16&quot;&gt;한 점에서 Dynamic Programming으로 Flooding 할 경우 현재까지의 최단 거리가 갱신된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 n-1번 째 점까지 모두 반복을 하면 전체 최단 경로가 갱신이 된다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벨만 포드는 음수 가중치도 갖고 있으므로 n번째에서 한번 더 최단 경로가 갱신이 된다면, 음수 사이클을 갖고 있다는 것이된다. 음수 사이클만 계속 돌면서 -INF 까지 떨어짐.&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;또 음수 가중치가 있기 때문에 INF일 경우 continue를 해주어야한다. 안그럼 OverFlow 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체적인 알고리즘 정리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 현재 노드에서 연결된 모든 간선의 가중치를 기준으로 최단거리를 갱신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 현재 노드의 가중치 + 다음 노드의 가중치 &amp;lt; 다음 노드의 가중치라면 현재 노드에서 다음 노드로 이동하는 길이 최단 경로이므로 업데이트 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 위 과정을 노드의 갯수 - 1번까지 반복하면 최단 경로가 갱신된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 2번까지 과정을 마치고 한번 더 최단 경로가 갱신된다면 음수 사이클이 존재하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://10000cow.tistory.com/entry/%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%95%9C-%EC%82%B4%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Bellman-Ford-Algorithm&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://10000cow.tistory.com/entry/%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%95%9C-%EC%82%B4%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Bellman-Ford-Algorithm&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1720274590095&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[벨만-포드 알고리즘] 한 살도 이해하는 벨만-포드 알고리즘(Bellman-Ford Algorithm)&quot; data-og-description=&quot;벨만-포드 알고리즘이란? 한 노드에서 다른 노드까지의 최단 거리를 구하는 알고리즘이다. 음의 가중치를 갖는 edge(간선)이 있을 때 사용하는 알고리즘이다. 다익스트라 알고리즘과 차이는 무엇&quot; data-og-host=&quot;10000cow.tistory.com&quot; data-og-source-url=&quot;https://10000cow.tistory.com/entry/%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%95%9C-%EC%82%B4%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Bellman-Ford-Algorithm&quot; data-og-url=&quot;https://10000cow.tistory.com/entry/%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%95%9C-%EC%82%B4%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Bellman-Ford-Algorithm&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/babrNV/hyWvNbXgjj/K8hb2JrzCoxQJdsko1dOe1/img.png?width=800&amp;amp;height=870&amp;amp;face=0_0_800_870,https://scrap.kakaocdn.net/dn/cloKuS/hyWvTiYenM/SyC3D14dJYXBl1QiciL06K/img.png?width=800&amp;amp;height=870&amp;amp;face=0_0_800_870,https://scrap.kakaocdn.net/dn/AHGyi/hyWvTQLNUP/okIjk5wqKZNwXiQ8zxwS10/img.png?width=876&amp;amp;height=953&amp;amp;face=0_0_876_953&quot;&gt;&lt;a href=&quot;https://10000cow.tistory.com/entry/%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%95%9C-%EC%82%B4%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Bellman-Ford-Algorithm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://10000cow.tistory.com/entry/%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%95%9C-%EC%82%B4%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%B2%A8%EB%A7%8C-%ED%8F%AC%EB%93%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Bellman-Ford-Algorithm&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/babrNV/hyWvNbXgjj/K8hb2JrzCoxQJdsko1dOe1/img.png?width=800&amp;amp;height=870&amp;amp;face=0_0_800_870,https://scrap.kakaocdn.net/dn/cloKuS/hyWvTiYenM/SyC3D14dJYXBl1QiciL06K/img.png?width=800&amp;amp;height=870&amp;amp;face=0_0_800_870,https://scrap.kakaocdn.net/dn/AHGyi/hyWvTQLNUP/okIjk5wqKZNwXiQ8zxwS10/img.png?width=876&amp;amp;height=953&amp;amp;face=0_0_876_953');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[벨만-포드 알고리즘] 한 살도 이해하는 벨만-포드 알고리즘(Bellman-Ford Algorithm)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;벨만-포드 알고리즘이란? 한 노드에서 다른 노드까지의 최단 거리를 구하는 알고리즘이다. 음의 가중치를 갖는 edge(간선)이 있을 때 사용하는 알고리즘이다. 다익스트라 알고리즘과 차이는 무엇&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;10000cow.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/알고리즘 종류</category>
      <category>Algorithm</category>
      <category>Bellman-Ford</category>
      <category>datastructrue</category>
      <category>Graph</category>
      <category>Minimum Spanning Tree</category>
      <category>백준</category>
      <category>벨만포드</category>
      <category>알고리즘</category>
      <category>최단거리</category>
      <category>최단경로</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/67</guid>
      <comments>https://dev-dot.tistory.com/entry/MST-Bellman-Ford-Algorithm#entry67comment</comments>
      <pubDate>Sat, 6 Jul 2024 23:15:49 +0900</pubDate>
    </item>
    <item>
      <title>Java Fast I/O 3 (feat. BOJ, String, StringBuilder)</title>
      <link>https://dev-dot.tistory.com/entry/Java-Fast-IO-3-feat-BOJ-String-StringBuilder</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;앞선 포스트와 마찬가지로 사람들은 PS에서 속도를 개선하기 위한 방법 중 하나로 StringBuilder를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;StringBuilder&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
    permits StringBuilder, StringBuffer {
    
    byte[] value;
    byte coder;
    boolean maybeLatin1;
    int count;
    private static final byte[] EMPTYVALUE = new byte[0];
    
    AbstractStringBuilder() {
        value = EMPTYVALUE;
    }
    
    public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
    }
    
}&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;StringBuilder의 추상 클래스이다. (여기서 Java Code Convention이 거슬린건 저뿐인가요?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StringBuilder는 내부에서 Buffer를 가지고 문자열을 추가하는 방식이라고 생각하면 된다.&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;size18&quot;&gt;&lt;b&gt;String&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String의 경우, Debug 해보면 해당 과정을 알 수 있는데 Assembly Level에서 먼저 String Builder를 생성하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String은 String Pool에서 관리되는 불변 객체이기 때문에 고정된 크기의 새로운 객체를 만들어야 하므로 가변 객체인 StringBuilder를 통해서 새로운 불변 객체인 String을 생성해낸다.&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;즉, String은 operator() + 연산 시 StringBuilder를 생성해서 String + String을 한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;    String a = &quot;a&quot;;
    String b = &quot;b&quot;;
    String c = new StringBuilder(a).append(b).toString();&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;이게 과연 진실일까? 가장 간단한 확인은 이 포스트를 확인하는 사람이 Debugging 을 직접해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 HashCode를 확인해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;    String test = &quot;test&quot;;
    final int beforeHash = System.identityHashCode(test);
    test += &quot;isSame?&quot;;
    final int afterHash = System.identityHashCode(test);
    System.out.println(&quot;before: &quot; + beforeHash + &quot;, after: &quot; + afterHash);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;before:&amp;nbsp;664740647,&amp;nbsp;after:&amp;nbsp;1804094807&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Performance Test&lt;/b&gt;&lt;/blockquote&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class StringOutputTest {

    public static void main(String[] args) {
       int iterations = 1;

       // Using String
       long startTime = System.nanoTime();
       String str = &quot;&quot;;
       for (int i = 0; i &amp;lt; iterations; i++) {
          str += &quot;a&quot;;
       }
       long endTime = System.nanoTime();
       System.out.println(&quot;String time: &quot; + (endTime - startTime) + &quot; ns&quot;);

       // Using StringBuilder
       startTime = System.nanoTime();
       StringBuilder sb = new StringBuilder();
       for (int i = 0; i &amp;lt; iterations; i++) {
          sb.append(&quot;a&quot;);
       }
       endTime = System.nanoTime();
       System.out.println(&quot;StringBuilder time: &quot; + (endTime - startTime) + &quot; ns&quot;);
    }

}
&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;String&amp;nbsp;time:&amp;nbsp;7897400&amp;nbsp;ns &lt;br /&gt;StringBuilder&amp;nbsp;time:&amp;nbsp;27000&amp;nbsp;ns&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 내가 똥컴이라 그런지 1번만 연산해도 이렇게 차이가 난다니..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 연산의 결과만 보더라도 String에서 새로운 StringBuilder를 생성하기 때문에 이렇게 차이가 나는 것을 알 수 있다.&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;String&amp;nbsp;time:&amp;nbsp;11001900&amp;nbsp;ns &lt;br /&gt;StringBuilder&amp;nbsp;time:&amp;nbsp;99400&amp;nbsp;ns &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력이 100개인 경우는 더욱 심하게 차이가 난다.&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;</description>
      <category>JAVA/기타</category>
      <category>+=</category>
      <category>string</category>
      <category>String Pool</category>
      <category>StringBuilder</category>
      <category>불변객체</category>
      <category>성능 개선</category>
      <category>시간 개선</category>
      <category>시간 복잡도</category>
      <category>자바 I/O</category>
      <category>자바 백준</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/66</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Fast-IO-3-feat-BOJ-String-StringBuilder#entry66comment</comments>
      <pubDate>Sat, 6 Jul 2024 22:54:39 +0900</pubDate>
    </item>
    <item>
      <title>Java Fast I/O 2 (feat. BOJ, StringTokenizer, String.split())</title>
      <link>https://dev-dot.tistory.com/entry/Java-Fast-IO-2-feat-BOJ-StringTokenizer-Stringsplit</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스트에는 StringTokenizer에 대해 작성해보려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS에서 어떻게든 속도를 조금 더 높여보려고 사람들이 여러 방법을 사용하죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 하나가 StringTokenizer 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정말 StringTokenizer의 성능이 그렇게 우수할까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 테스트 해봤습니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package com.study.datastructrue.string;

import java.util.StringTokenizer;

public class DevidePerformTest {
    public static void main(String[] args) {
       String str = &quot;one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five one two three four five&quot;;
       //String str = &quot;일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 일 이 삼 사 오 &quot;;

       long startTime = System.nanoTime();
       String[] splitArray = str.split(&quot; &quot;);
       long endTime = System.nanoTime();
       System.out.println(&quot;String.split() time: &quot; + (endTime - startTime) + &quot; ns&quot;);

       startTime = System.nanoTime();
       StringTokenizer tokenizer = new StringTokenizer(str);
       endTime = System.nanoTime();
       System.out.println(&quot;StringTokenizer time: &quot; + (endTime - startTime) + &quot; ns&quot;);

       System.out.println(&quot;String.split() result:&quot;);
       for (String s : splitArray) {
          System.out.print(s);
       }
       System.out.println();

       System.out.println(&quot;StringTokenizer result:&quot;);
       while (tokenizer.hasMoreTokens()) {
          System.out.print(tokenizer.nextToken());
       }
    }
}&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;이게 JDK 11이든 21이든 속도가 똑같더라구요.&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;ASCII 기반 짧은 문자열 split() &amp;gt; Tokenizer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASCII 기반 긴 문자열 split() &amp;lt; Tokenizer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNICODE 기반 문자열 split() &amp;lt; Tokenizer&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 따로 내부는 뜯어서 설명하지는 않겠습니다. (너무 복잡함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신, StringTokenizer를 분석하신 포스트가 있습니다. (&lt;a href=&quot;https://blog.naver.com/PostView.nhn?blogId=chogahui05&amp;amp;logNo=221474002967&amp;amp;categoryNo=12&amp;amp;parentCategoryNo=0&amp;amp;viewDate=&amp;amp;currentPage=1&amp;amp;postListTopCurrentPage=1&amp;amp;from=postView&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;여기&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 PS에서 시간 효율을 크게 따지는 데이터는 N &amp;gt;= 10,000 인 경우가 대다수이니까 StringTokenizer를 사용하는게 좋을 것 같네요. 추가로 &lt;a href=&quot;https://blog.naver.com/makga87/221949199317&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;해당 포스트&lt;/a&gt;에서 자세한 설명을 해두었더라구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 제 테스트 코드의 경우, 구분자를 공백(&quot; &quot;)으로 해두었습니다. 위 포스트에서 말하기를 구분자가 유니코드가 아닌 아스키코드라면, split()이 더 빠르다. (StringTokenizer가 Unicode에 대해 설계하지 않은 Legacy Code이기 때문이다.)&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;</description>
      <category>JAVA/기타</category>
      <category>fast i/o</category>
      <category>string.split()</category>
      <category>stringTokenizer</category>
      <category>백준 속도</category>
      <category>백준 입출력</category>
      <category>백준 자바</category>
      <category>성능 개선</category>
      <category>시간복잡도</category>
      <category>자바 속도</category>
      <category>자바 입출력</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/65</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Fast-IO-2-feat-BOJ-StringTokenizer-Stringsplit#entry65comment</comments>
      <pubDate>Sat, 6 Jul 2024 22:23:06 +0900</pubDate>
    </item>
    <item>
      <title>Java Fast I/O (feat. BOJ, BufferedReader, BufferedWriter)</title>
      <link>https://dev-dot.tistory.com/entry/Java-Fast-IO-feat-BOJ-BufferedReader-BufferedWriter</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;BOJ JAVA 풀이에서 왜 BufferedReader, BufferedWriter 를 사용할까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람들은 PS 중 시간 효율을 조금이라도 올리기 위해서 Fast I/O를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 I/O 속도는 Default I/O, Fast I/O, Custom Fast I/O 가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;찐 고수들은 종종 Custom Fast I/O를 사용하는 것을 볼 수 있는데 나는 기본적인 Fast I/O만 사용한다. (초보)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python 에서는 sys.stdin.readline, C++ 에서는 ios_base::sync_with_stdio(0), C에서는 fread() 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java에서는 BufferedReader 나 BufferedWriter를 사용하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 왜 사용하는지 한 번 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;BufferedReader vs Scanner&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;BufferedReader&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720093908606&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;   public class BufferedReader extends Reader {
    private Reader in;

    private char[] cb;

    private static final int DEFAULT_CHAR_BUFFER_SIZE = 8192;
    
    public BufferedReader(Reader in, int sz) {
        super(in);
        if (sz &amp;lt;= 0)
            throw new IllegalArgumentException(&quot;Buffer size &amp;lt;= 0&quot;);
        this.in = in;
        cb = new char[sz];
        nextChar = nChars = 0;
    }

    public BufferedReader(Reader in) {
        this(in, DEFAULT_CHAR_BUFFER_SIZE);
    }

}&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;자바에서 구현하는 BufferedReader Class 정보다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 8Byte의 char 자료형을 저장할 수 있는 Buffer를 가지고 있고 생성값에 따라 더 늘릴 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 8Byte의 문자를 read 할 수 있다고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Scanner&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public final class Scanner implements Iterator&amp;lt;String&amp;gt;, Closeable {

    private CharBuffer buf;
    private static final int BUFFER_SIZE = 1024;
    private int position;
    private Matcher matcher;
    private Pattern delimPattern;
    private Pattern hasNextPattern;
    private int hasNextPosition;
    private String hasNextResult;
    private Readable source;
    private boolean sourceClosed = false;
    private boolean needInput = false;
    private boolean skipped = false;
    private int savedScannerPosition = -1;
    private Object typeCache = null;
    private boolean matchValid = false;
    private boolean closed = false;
....
}&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;Scanner 이 녀석은 뭐가 너무 많다. 기본적으로 1KB의 Buffer를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 와중에 buffer도 User Defined Data Type이다. 헐&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public Scanner(InputStream source) {
    this(new InputStreamReader(source), WHITESPACE_PATTERN);
}

public String nextLine() {
    modCount++;
    if (hasNextPattern == linePattern())
        return getCachedResult();
    clearCaches();

    String result = findWithinHorizon(linePattern, 0);
    if (result == null)
        throw new NoSuchElementException(&quot;No line found&quot;);
    MatchResult mr = this.match();
    String lineSep = mr.group(1);
    if (lineSep != null)
        result = result.substring(0, result.length() - lineSep.length());
    if (result == null)
        throw new NoSuchElementException();
    else
        return result;
}&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;이건 Scanner 생성자랑 Input Method 코드인데 생성할 때부터 무슨 패턴 검사를하고 입력받을 때도 패턴 검사를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얘는 그냥 BufferedReader보다 느릴 수 밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 패턴검사나 기능 측면에서는 장점이 있으니까 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Performance Test&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class InputTest {

    public static void main(String[] args) throws IOException {
        long startTime, endTime;
        String input = &quot;&quot;;
        for (int i = 0; i &amp;lt; 100000; i++) {
            input += &quot;AAAAAAAAAAAAAAAAAAAA&quot;;
        }
        System.setIn(new ByteArrayInputStream(input.getBytes()));

        // fread
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        startTime = System.nanoTime();
        String line = br.readLine();
        endTime = System.nanoTime();
        System.out.println(&quot;BufferedReader read time: &quot; + (endTime - startTime) + &quot; ns&quot;);


        System.setIn(new ByteArrayInputStream(input.getBytes()));

        // read
        Scanner sc = new Scanner(System.in);
        startTime = System.nanoTime();
        line = sc.nextLine();
        endTime = System.nanoTime();
        System.out.println(&quot;Scanner read time: &quot; + (endTime - startTime) + &quot; ns&quot;);
    }

}&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;BufferedReader&amp;nbsp;read&amp;nbsp;time:&amp;nbsp;19981900&amp;nbsp;ns &lt;br /&gt;Scanner&amp;nbsp;read&amp;nbsp;time:&amp;nbsp;102158800&amp;nbsp;ns&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;그냥 데이터가 커질수록 무진장 차이난다. 무조건 PS에서는 BufferedReader를 사용해야겠다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;BufferedWriter vs System.out&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;BufferedWriter&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class BufferedWriter extends Writer {
    private static final int DEFAULT_INITIAL_BUFFER_SIZE = 512;
    private static final int DEFAULT_MAX_BUFFER_SIZE = 8192;

    private Writer out;

    private char[] cb;
    
    public BufferedWriter(Writer out, int sz) {
        this(out, sz, sz);
    }

    private void implFlushBuffer() throws IOException {
        ensureOpen();
        if (nextChar == 0)
            return;
        out.write(cb, 0, nextChar);
        nextChar = 0;
    }
    
}&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;얘도 마찬가지로 Buffer를 사용하는데 자세하게 뜯어보지 않아도 변수명에 명시해준 덕에 512Byte ~ 8KB의 버퍼가 허용되구나를 예상할 수 있다. 그리고 BufferedWriter 객체를 잘 뜯어보면 write() 메서드를 실행할 때, implFushBuffer() 메서드를 실행하게 된다는 것을 알 수 있다. 그런데 BufferedWriter의 implFushBuffer는 out.write 메서드를 수행하고 있고 out 변수의 객체가 Writer인 것을 알고 있자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;System.out.print...&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public final class System {
    public static final PrintStream out = null;
}


public class PrintStream extends FilterOutputStream implements Appendable, Closeable {
    private BufferedWriter textOut;
    private OutputStreamWriter charOut;
    
    private void implWrite(String s) throws IOException {
    ensureOpen();
    textOut.write(s);
    textOut.flushBuffer();
    charOut.flushBuffer();
    if (autoFlush &amp;amp;&amp;amp; (s.indexOf('\n') &amp;gt;= 0))
        out.flush();
	}
}&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;System 객체에서 출력을 하는 out은 PrintStream 객체이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 우리는 PrintStream 객체에서 제공하는 write() 메소드로 출력을하는데 이것을 뜯어보면 BufferedWriter에서 출력을 하고 있다는 것이다! 그럼 BufferedWriter에서 Writer 객체로 출력한다는 것을 알았는데, 결국 System.out 이나 BufferedWriter는 모두 다 Writer 객체로 출력하고 있다는 것이다.&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;그럼 도대체 왜 BufferedWriter를 따로 쓰냐?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BufferedWriter는 캐시 크기를 직접 수정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. System.out.print()는 매번 Default 크기의 BufferedWirter를 불러와야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. System.out.print()는 BufferedWriter의 버퍼 외에 charOut.flushBuffer(), out.flush() 로 스트림을 비우는 추가 작업을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이해하기 쉽도록 설명하자면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BufferedWriter는 1kg ~ 1000kg 용량을 담을 수 있는 장바구니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. System.out.print는 1kg 장바구니만 지원한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이것으로 인해 어떤 차이가 발생할까?&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;우리가 버퍼를 사용하기 위해서는 OS로부터 메모리를 할당받아야 한다.&lt;br /&gt;1. BufferedWriter로 한 번에 1000kg을 담을 수 있는 장바구니(메모리)를 구한다.&lt;br /&gt;한 번에 1000kg의 물건(문자열)을 담고 바로 전달한다.&lt;br /&gt;대신, 물건(자원))이 1000kg(할당된 메모리량)을 초과할 경우 여러번 전송해야한다.&lt;br /&gt;이 때, 1000kg의 내용물을 비우고 다시 채우는데 상당한 시간이 소요된다.&lt;br /&gt;&lt;br /&gt;2. System.out.writer로 한 번에 1kg을 담을 수 있는 장바구니(메모리)를 구한다.&lt;br /&gt;매번 1kg의 물건을 담고 전달한다. 마찬가지로, 한번 전달 시 물건이 1kg을 초과할 경우 내부에서 장바구니를 비우고 다시 채우는 시간이 소요된다.&lt;br /&gt;&lt;br /&gt;즉, 대량의 물건(데이터)을 BufferedWriter로 전송할 경우 효과적이다.&lt;br /&gt;소량의 물건도 BufferedWriter로 전송할 경우 효과적이다. (대신 버퍼 크기를 줄여야함)&lt;br /&gt;-&amp;gt; System.out.print.. 의 경우, 스트림도 비우는데 자동차에서 장바구니가 위치할 자리를 깨끗하게 청소한다는 정도로만 생각해도 될 것 같다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Performance Test&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #131314; color: #ebebeb;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;package com.study.datastructrue.io;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class OutputTest {

    public static void main(String[] args) throws IOException {
        long bufferStartTime, bufferEndTime;
        long printStartTime, printEndTime;

        int numIterations = 1000;
        String data = &quot;Hello World\n&quot;;

        // large buffer, max size = 8 KB
        BufferedWriter bwLarge = new BufferedWriter(new OutputStreamWriter(System.out), 8192);
        long largeBufferStartTime = System.nanoTime();
        for (int i = 0; i &amp;lt; numIterations; i++) {
            bwLarge.write(data);
        }
        bwLarge.flush();
        long largeBufferEndTime = System.nanoTime();

        // default buffer = 512 Byte
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        bufferStartTime = System.nanoTime();
        for (int i = 0; i &amp;lt; numIterations; i++) {
            bw.write(data);
        }
        bw.flush();
        bufferEndTime = System.nanoTime();


        // System.out.print()
        printStartTime = System.nanoTime();
        for (int i = 0; i &amp;lt; numIterations; i++) {
            System.out.print(data);
        }
        printEndTime = System.nanoTime();

        System.out.println(&quot;BufferedWriter (default buffer) write time: &quot; + (bufferEndTime - bufferStartTime) + &quot; ns&quot;);
        System.out.println(&quot;BufferedWriter (large buffer) write time: &quot; + (largeBufferEndTime - largeBufferStartTime) + &quot; ns&quot;);
        System.out.println(&quot;System.out.print write time: &quot; + (printEndTime - printStartTime) + &quot; ns&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 68px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 14.5349%; height: 17px;&quot;&gt;numIterators&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 16.2791%;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 14.186%; height: 17px;&quot;&gt;10&lt;/td&gt;
&lt;td style=&quot;width: 17.093%; height: 17px;&quot;&gt;100&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%; height: 17px;&quot;&gt;1000&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%;&quot;&gt;10000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 14.5349%; height: 17px;&quot;&gt;Default Buffer&lt;/td&gt;
&lt;td style=&quot;width: 16.2791%; height: 17px;&quot;&gt;31100&amp;nbsp;ns&lt;/td&gt;
&lt;td style=&quot;width: 14.186%; height: 17px;&quot;&gt;158900 ns&lt;/td&gt;
&lt;td style=&quot;width: 17.093%; height: 17px;&quot;&gt;262700 ns&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%; height: 17px;&quot;&gt;24384500 ns&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%;&quot;&gt;196324900 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 14.5349%; height: 17px;&quot;&gt;Large Buffer&lt;/td&gt;
&lt;td style=&quot;width: 16.2791%; height: 17px;&quot;&gt;156400&amp;nbsp;ns&lt;/td&gt;
&lt;td style=&quot;width: 14.186%; height: 17px;&quot;&gt;246900 ns&lt;/td&gt;
&lt;td style=&quot;width: 17.093%; height: 17px;&quot;&gt;407100 ns&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%; height: 17px;&quot;&gt;2100000 ns&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%;&quot;&gt;281576200 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 14.5349%; height: 17px;&quot;&gt;System.out&lt;/td&gt;
&lt;td style=&quot;width: 16.2791%; height: 17px;&quot;&gt;38800&amp;nbsp;ns&lt;/td&gt;
&lt;td style=&quot;width: 14.186%; height: 17px;&quot;&gt;449300 ns&lt;/td&gt;
&lt;td style=&quot;width: 17.093%; height: 17px;&quot;&gt;2504500 ns&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%; height: 17px;&quot;&gt;26867900 ns&lt;/td&gt;
&lt;td style=&quot;width: 18.8954%;&quot;&gt;263278000 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 PC의 성능마다 결과는 다르겠지만, Buffer가 클수록 비우는데 시간이 꽤 소요가 된다는 것을 알 수가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS에서는 대부분 출력결과가 1000개 이하이기 때문에 LargeBuffer로 해도 될 듯,,?&lt;/p&gt;</description>
      <category>JAVA/기타</category>
      <category>BufferedReader</category>
      <category>BufferedWriter</category>
      <category>fast i/o</category>
      <category>Java I/O</category>
      <category>PS</category>
      <category>백준</category>
      <category>실행속도</category>
      <category>알고리즘</category>
      <category>알고리즘 시간</category>
      <category>자바 입출력</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/64</guid>
      <comments>https://dev-dot.tistory.com/entry/Java-Fast-IO-feat-BOJ-BufferedReader-BufferedWriter#entry64comment</comments>
      <pubDate>Sat, 6 Jul 2024 00:49:35 +0900</pubDate>
    </item>
    <item>
      <title>18. 상호배제 구현 방법</title>
      <link>https://dev-dot.tistory.com/entry/18-%EC%83%81%ED%98%B8%EB%B0%B0%EC%A0%9C-%EA%B5%AC%ED%98%84-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 해당 포스팅은 단일 프로세서 상호배제 구현 방법인 것을 알고 있어야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인터럽트 서비스 금지 방법&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buslGf/btsH1oRgHUD/UphMkntNkz9dlBucRF51F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buslGf/btsH1oRgHUD/UphMkntNkz9dlBucRF51F0/img.png&quot; data-alt=&quot;그림1. 인터럽트 서비스 금지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buslGf/btsH1oRgHUD/UphMkntNkz9dlBucRF51F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuslGf%2FbtsH1oRgHUD%2FUphMkntNkz9dlBucRF51F0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;371&quot; height=&quot;238&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림1. 인터럽트 서비스 금지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진입 코드(Entry Code)에서 cli(clear interrupt flag) 명령으로 인터럽트 서비스를 중지하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임계 구역(Critical Code)에서 인터럽트가 발생하면 무시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진출 코드(Exit Code)에서 sti(set interrupt flag) 명령으로 인터럽트 서비스를 재실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckkxsn/btsH00pGuqF/fuaqM5wPAeQl4PUgOTwaZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckkxsn/btsH00pGuqF/fuaqM5wPAeQl4PUgOTwaZ0/img.png&quot; data-alt=&quot;그림2. T1 인터럽트 발생&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckkxsn/btsH00pGuqF/fuaqM5wPAeQl4PUgOTwaZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckkxsn%2FbtsH00pGuqF%2FfuaqM5wPAeQl4PUgOTwaZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;358&quot; height=&quot;206&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림2. T1 인터럽트 발생&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트 서비스를 중지하지 않을 경우, 그림2와 같이 T1이 임계구역을 접근했을 때, T1에게서 인터럽트 서비스가 발생하면 스레드는 대기 상태가 되고 T2를 스케줄한다. 이 때, T2가 임계 구역에 접근하게 된다면 공유 자원에 T1과 T2가 공존하는 현상이 발생한다. 즉 T1이 변수의 값을 읽고 인터럽트가 발생한다면 변수의 값이 동기화되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트 서비스 금지 상호배제 방법은 스레드 동기화를 해결할 수 있지만 문제점도 존재한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Single Core CPU에서 고안된 방법으로 임계구역을 처리하는 도중 모든 인터럽트 서비스를 무시하게 된다.&lt;/li&gt;
&lt;li&gt;Multi Core CPU에서도 다른 CPU의 인터럽트 서비스를 무시하는 문제점이 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문제의 해결 방법으로 CPU의 LOCK 핀에 신호를 발생시키는 LOCK 신호를 이용해서 현재 액세스 중인 메모리에 다른 프로세스가 접근하지 못하도록 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;283&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1FZxr/btsH0Vvhskd/ObvTywkSVpcLf0AU8Skt5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1FZxr/btsH0Vvhskd/ObvTywkSVpcLf0AU8Skt5k/img.png&quot; data-alt=&quot;그림 3. Locking / UnLocking&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1FZxr/btsH0Vvhskd/ObvTywkSVpcLf0AU8Skt5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1FZxr%2FbtsH0Vvhskd%2FObvTywkSVpcLf0AU8Skt5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;596&quot; height=&quot;283&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;283&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 3. Locking / UnLocking&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lock 신호를 이용하는 방식도 문제점이 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. T1이 mov ax, lock 까지 처리 중일 때, &amp;amp;ax 에는 0이 저장되어 있으므로 임계구역에 접근할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이 때, T1의 Time Slice가 만료되어 T2가 스케줄된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. T1이 mov lock, 1을 연산을 수행하지 않았으므로 T2는 mov ax, lock 연산을 처리하면서 &amp;amp;ax는 0이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. T2는 ax가 0이므로 임계구역에 진입하였고 도중 Time Slice가 만료되어 T1이 재수행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. T1은 컨텍스트 정보에 다음 명령인 mov lock, 1을 수행해야한다. 하지만 이미 lock은 1이지만 상관없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. T1은 1에서 ax 값이 0이므로 cmp ax, 0 연산을 수행하고 임계구역에 진입하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 6개 과정에서 임계구역에는 T1과 T2이 공존하게 되는 문제점이 발생한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;원자 명령(Atmoic Instruction) 사용&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Locking의 문제점을 해결하기 위해 고안된 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mov ax, lock 과 move lock, 1 을 동시에 수행하는 TSL ax, lock 이라는 원자 명령을 통해 ax에 lock 정보를 담으면서 locking을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 인터럽트 서비스 금지와 원자 명령 사용을 통해 상호배제를 구현하는 방법을 알아봤다. 하지만, 이 방법은 단일 프로세스에서도 문제가 존재하고 멀티 프로세서가 도입되면서 복잡해지는 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에는 멀티 프로세서에서는 어떻게 상호배제를 처리하는지 포스팅해보자.&lt;/p&gt;</description>
      <category>CS/운영체제</category>
      <category>CS</category>
      <category>locking</category>
      <category>OS</category>
      <category>상호배제</category>
      <category>상호배제구현</category>
      <category>운영체제</category>
      <category>원자 명령</category>
      <category>인터럽트 서비스</category>
      <category>임계구역</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/63</guid>
      <comments>https://dev-dot.tistory.com/entry/18-%EC%83%81%ED%98%B8%EB%B0%B0%EC%A0%9C-%EA%B5%AC%ED%98%84-%EB%B0%A9%EB%B2%95#entry63comment</comments>
      <pubDate>Sun, 16 Jun 2024 00:23:22 +0900</pubDate>
    </item>
    <item>
      <title>17. 상호 배제 (Mutual Exclusion)</title>
      <link>https://dev-dot.tistory.com/entry/17-%EC%83%81%ED%98%B8-%EB%B0%B0%EC%A0%9C-Mutual-Exclusion</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상호배제란?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 스레드 동기화에서 언급된 임계구역과 상호배제는 스레드 동기화를 위한 중요한 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 임계 구역(Critical Section)은 각 스레드들이 동시에 접근할 수 있는 공유 데이터를 관리하는 구역이다.&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;스레드 A는 횟집, 스레드 B는 매운탕 집이다. 스레드 A와 B는 수산도매에서 싱싱한 생선을 가져와야한다. 스레드 A와 B는 서로 경매가를 부르고 있는데 도매상이 &quot;마지막으로 현재 경매가 보다 높은 가격을 먼저 제시한 사람에게 판매하겠습니다.&quot;라고 했다. 스레드 A와 B는 동시에 &quot;100만 원!&quot;을 외쳤다. 이 때, 도매상은 누가 먼저 제시 했는지 몰라서 난감한 상황에 빠진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 앞에 부저가 있었고 먼저 부저를 누른 사람이 있을 경우 다른 부저가 동작하지 않는 시스템이 있다면 순서를 정확히 알 수 있다. 여기서 수산도매가 임계 구역, 부저가 상호 배제로 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;상호배제&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반 코드(non-critical code) : 각 스레드에서 처리하는 코드이다.&lt;/li&gt;
&lt;li&gt;임계구역 진입 코드(entry code) : 임계 구역에 다른 스레드가 있는지 확인한다. 다른 스레드가 없다면 현재 스레드가 임계구역에 진입하게 되고 다른 스레드가 존재한다면 대기한다. 상호배제의 시작이다.&lt;/li&gt;
&lt;li&gt;임계구역 코드(critical code) : 한 스레드가 순서를 보장받고 공유 자원에 실제적으로 접근하는 코드이다.&lt;/li&gt;
&lt;li&gt;임계구역 진출 코드(exit code) : 임계구역에서의 처리가 끝났다면 다른 스레드가 진입할 수 있도록 상호배제를 종료하는 코드이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;상호배제를 구현하는 방법&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SW적, HW적으로 구현하는 방법이 있는데 오늘날에는 주로 HW 솔루션을 사용한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트 서비스 금지 방법, 원자 기계 명령(atomic instruction) 사용 방법&lt;/p&gt;</description>
      <category>CS/운영체제</category>
      <category>CS</category>
      <category>It</category>
      <category>OS</category>
      <category>상호배제</category>
      <category>상호배제 구현</category>
      <category>운영체제</category>
      <category>원자 기계 명령</category>
      <category>인터럽트 서비스 금지</category>
      <category>임계구역</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/62</guid>
      <comments>https://dev-dot.tistory.com/entry/17-%EC%83%81%ED%98%B8-%EB%B0%B0%EC%A0%9C-Mutual-Exclusion#entry62comment</comments>
      <pubDate>Sat, 15 Jun 2024 22:00:20 +0900</pubDate>
    </item>
    <item>
      <title>16. 스레드 동기화 (Thread Synchronization)</title>
      <link>https://dev-dot.tistory.com/entry/16-%EC%8A%A4%EB%A0%88%EB%93%9C-%EB%8F%99%EA%B8%B0%ED%99%94-Thread-Synchronization</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스레드 동기화란 뭘까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드 동기화란 다수의 스레드가 하나의 자원에 동시에 접근할 때 발생할 수 있는 문제점을 해결할 수 있는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다수의 스레드가 하나의 자원에 동시에 접근한다는게 무슨 말일까?&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스레드 동기화 이해하기&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 컴퓨터의 구조를 잘 알고 있어야한다.&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;size18&quot;&gt;&lt;b&gt;이해를 해보자.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터는 클럭 단위로 동작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클럭 단위로 동작한다는 것은 하나의 작업을 수행할 때, 일정 시간이 소요된다는 의미이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TEMP = 10 이 있을 때, 하나의 클럭이 소요되는데 0.001초라고 해보자.&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;스레드 A와 B가 TEMP에 입력한 값을 더하려고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 0초에 스레드 A는 TEMP의 값을 확인한다. 값은 10이다. 5를 더한다. 더하기 작업은 2클럭이 소요된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 더하기 작업으로 인한 시스템 콜 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 0.001초에 스레드 B는 TEMP의 값을 확인한다. 아직 스레드 A의 작업이 끝나지 않아서 TEMP는 여전히 10이다. 마찬가지로 스레드 B도 5를 더하는 연산을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 더하기 작업으로 인한 시스템 콜 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 0.002초에 스레드 A의 작업이 끝나고 TEMP에는 15가 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 0.003초에 스레드 B의 작업이 끝나고 TEMP에는 15가 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로 연산된 TEMP의 결과는 15가 되는 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트 외에도 타임슬라이스(TimeSlice) 등의 문제로 스케줄링이 바뀔 때도 이런 문제가 발생할 수 있다.&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;A와 B가 실제로 동시에 작업을 한 것은 아니지만, 컴퓨터 구조 상 인간의 눈에는 동시에 작업을 수행한 것 처럼 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 문제를 동시 접근 문제라고 하고 해결하기 위한 방법이 스레드 동기화이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드뿐만 아니라 프로세스도 해당 문제를 가지고 있다. 왜냐하면 각 스레드와 각 프로세스는 독립적이기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 할 일만 한다는 것이다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 문제점은 다중 코어나 커널 코드에서 매우 많이 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전문가들은 이 문제를 해결하기 위해서 Thread Synchronization 이 필요했고 이에 대한 중요한 두 개념이 나왔다.&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;임계구역(Critical Section)과 상호배제(mutual exclusion)이다.&lt;/p&gt;</description>
      <category>CS/운영체제</category>
      <category>critical section</category>
      <category>CS</category>
      <category>Mutual Exclusion</category>
      <category>OS</category>
      <category>thread synchronization</category>
      <category>상호배제</category>
      <category>스레드 동기화</category>
      <category>운영체제</category>
      <category>임계구역</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/61</guid>
      <comments>https://dev-dot.tistory.com/entry/16-%EC%8A%A4%EB%A0%88%EB%93%9C-%EB%8F%99%EA%B8%B0%ED%99%94-Thread-Synchronization#entry61comment</comments>
      <pubDate>Sat, 15 Jun 2024 21:27:07 +0900</pubDate>
    </item>
    <item>
      <title>4. Physical Layer - Digital Signals</title>
      <link>https://dev-dot.tistory.com/entry/4-Physical-Layer-Digital-Signals</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crSNxW/btsGSla9hEJ/xQk8oVuLJlpNkuZCiizGf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crSNxW/btsGSla9hEJ/xQk8oVuLJlpNkuZCiizGf0/img.png&quot; data-alt=&quot;그림 A. 디지털 신호&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crSNxW/btsGSla9hEJ/xQk8oVuLJlpNkuZCiizGf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrSNxW%2FbtsGSla9hEJ%2FxQk8oVuLJlpNkuZCiizGf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;459&quot; height=&quot;341&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 A. 디지털 신호&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 신호는 0과 1로 표현할 수 있는 실제 전기 신호이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물리 계층에서는 실제 전기를 통해 bit 정보를 전송하기 때문에 디지털 신호에 대해 알고 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Bit Rate (비트 전송률)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1초 당 비트 전송률이고 Bit Per Second로 bps라고도 한다. 물리적인 장치로 디지털 데이터를 전달할 때 디지털 신호로 전달하게 되는데 그림 A와 같이 bit rate가 몇 bit냐에 따라서 디지털 신호의 레벨을 나누게 된다.&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;한 줄당 80글자가 있는 문장이 총 24줄 있다고 가정하자. 이를 한 페이지라고 했을 때 총 100페이지가 있다면 이 정보를 채널을 통해 전송하는 Bit Rate는 어떻게 될까? 한 글자는 1Byte = 8bit 이므로 8 * 80 * 24 * 100 으로 1,536,000bps가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.536 * 10^6 bps로 1.536Mbps로 표현한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;디지털 신호를 어떻게 전송할까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 신호가 복합 아날로그 신호라는 것을 알아야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 그럴까? 그 이유는 푸리에 변환을 공부해야 알게 되는데,,, 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간략히 설명하자면, 통신에서 디지털신호(이산 신호)를 표현하기 위해서 푸리에 변환이라는 공식을 통해 되게 짧은 Time Slice로 나타낸다. 반대로 디지털 신호를 이산신호로 표현하기 위해 아날로그 신호의 합으로 디지털 신호처럼 보이도록 한다. 자세한 내용은 디지털 신호 처리나 응용 수학에서 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4m8ej/btsGTYTlRIp/eDM8KkGdhsdwyxmY2BwRL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4m8ej/btsGTYTlRIp/eDM8KkGdhsdwyxmY2BwRL0/img.png&quot; data-alt=&quot;그림 B. 아날로그 신호의 이산 신호 표현법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4m8ej/btsGTYTlRIp/eDM8KkGdhsdwyxmY2BwRL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4m8ej%2FbtsGTYTlRIp%2FeDM8KkGdhsdwyxmY2BwRL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;493&quot; height=&quot;166&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 B. 아날로그 신호의 이산 신호 표현법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주파수가 높은 아날로그 신호를 합치면 합칠수록 이산신호의 가까운 모습을 띄게 된다. 그래서 무한한 대역폭을 가진 경우, 디지털 신호는 주파수 도메인에서 복합 아날로그 신호로 관측된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Baseband Transmission&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Baseband 신호는 원래의 신호 그 자체를 의미하는 것이다. 즉, 주파수 도메인 상 표현되는 0Hz 부터 최대 주파수까지 표현되는 모든 정보를 Baseband 신호라고 한다. Baseband 전송은 디지털 신호를 복합 아날로그 신호로 바꾸는 과정이 복잡하므로 아날로그 신호로 변경하지 않고 Channel을 통해 디지털 신호 그 자체(Baseband)를 보내는 것이다.&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;그럼, 앞에서 했던 말을 생각해보자. 디지털 신호는 주파수 범위가 무한하므로 대역폭이 넓을 수록 필요 없는 정보까지 같이 전달하게 될 것이다. 그래서 디지털 통신에서 Baseband 전송을 하게 된다면 Low-pass filter를 통해서 의미있는 정보만 추출해서 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xMQyC/btsGTGyBQP8/dBS2ejku2yGYNfKOAQkDM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xMQyC/btsGTGyBQP8/dBS2ejku2yGYNfKOAQkDM0/img.png&quot; data-alt=&quot;Baseband 전송에서 넓은 대역폭을 가진 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xMQyC/btsGTGyBQP8/dBS2ejku2yGYNfKOAQkDM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxMQyC%2FbtsGTGyBQP8%2FdBS2ejku2yGYNfKOAQkDM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;557&quot; height=&quot;101&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;101&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Baseband 전송에서 넓은 대역폭을 가진 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/20vzx/btsGTjcATsn/znhUuumQXyGqFKutxMQmrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/20vzx/btsGTjcATsn/znhUuumQXyGqFKutxMQmrk/img.png&quot; data-alt=&quot;Low-pass channel로 의미있는 값만 추출한 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/20vzx/btsGTjcATsn/znhUuumQXyGqFKutxMQmrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F20vzx%2FbtsGTjcATsn%2FznhUuumQXyGqFKutxMQmrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;117&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;117&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Low-pass channel로 의미있는 값만 추출한 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 특성을 이용한다면, 대역폭이 넓을 수록 원래의 디지털 신호에 가까운 형태로 복원할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2pv5X/btsGTi5PD5z/1bFHNfvQ2K2iK0h59gsNzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2pv5X/btsGTi5PD5z/1bFHNfvQ2K2iK0h59gsNzK/img.png&quot; data-alt=&quot;넓은 대역폭을 이용한 디지털 신호의 복원&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2pv5X/btsGTi5PD5z/1bFHNfvQ2K2iK0h59gsNzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2pv5X%2FbtsGTi5PD5z%2F1bFHNfvQ2K2iK0h59gsNzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;709&quot; height=&quot;205&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;넓은 대역폭을 이용한 디지털 신호의 복원&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Broadband Transmission&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 신호를 전송하는 방법에는 Broadband 전송 방식도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Broadband 전송 방식은 디지털 신호를 그대로 전송하는 것이 아닌 아날로그 신호로 변환한 뒤 전송하는 것이다. 이 과정에서 사용되는 것이 변조(Modulation)라는 개념인데 Modulation을 통해 디지털 신호를 아날로그 신호로 변환한다. 아날로그 신호로 변환 후 주파수에 맞는 Bandpass Channel을 통해서 신호를 전송하는 것이다.&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;'Baseband와 큰 차이가 없는데 왜 사용할까?' 이런 생각이 들었다면 정말 좋은 접근이라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 통신에서 Broadband와 Baseband의 차이는 디지털 신호 그대로 전송하기 vs 아날로그 신호로 변환해서 전송하기로 생각할 수 있다. 단순히 생각하면 변조 과정을 거치고 보내는걸 사용할 바에 Baseband 신호를 그냥 보내는게 훨씬 빠르고 좋다고 할 수 있다. 그럼에도 데이터 통신에서 Broadband를 설명하는 이유는 나중에 나올 Multiplexing 개념 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tL5Vv/btsGRz1QiRV/RiKQQS47P7gEyWxxMXJzAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tL5Vv/btsGRz1QiRV/RiKQQS47P7gEyWxxMXJzAk/img.png&quot; data-alt=&quot;Broadband Transmission&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tL5Vv/btsGRz1QiRV/RiKQQS47P7gEyWxxMXJzAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtL5Vv%2FbtsGRz1QiRV%2FRiKQQS47P7gEyWxxMXJzAk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;510&quot; height=&quot;262&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Broadband Transmission&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 설명해서, 우리가 Channel을 통해서 신호를 보낸다고 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신호A는 10hz~50hz의 정보가 있고 신호 B는 51hz~60hz 정보가 있고, 신호 C는 30hz~50hz 정보가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채널A는 10hz~50hz bandwidth를 채널B는 51hz~60hz bandwidth를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신호 A,B,C가 동시에 신호를 보낸다면 신호 A와 B는 각 각 채널 A, B를 선택하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 채널 C는? 여기서 문제가 발생한다. 채널 A를 선택하면 신호 A와 충돌, 채널 B를 선택하면 신호 B와 충돌...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 문제점을 전송 장애라고 하고 해결할 수 있는 방법이 Multiplexing 개념을 사용한 Broadband Transmission 이다.&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;자세한 Multiplexing 내용은 다른 포스트에 설명하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Transmission Impairment&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 장애는 크게 3가지가 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;감쇠(Attenuation)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 음성만 한 번 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아~~ 하고 소리를 내면 일정 거리가 지나면 소리가 작아지거나 안들린다. 이런 현상이 감쇠이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통신에서 신호도 음파와 같은 파동이므로 일정 구간을 지나면 작아질 수 밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감쇠 정도를 확인하는 방법이 데시벨(dB)인데 전기 쪽에서는 전기의 세기, 디지털 신호에서는 신호의 세기로 사용하는 단위다. 통신에서는 디지털 신호이므로 신호의 세기 개념이 적용되는데 dB로 신호의 감쇠(세기가 얼마나 약해졌는지) 정도를 알 수 있다. dB을 구하는 방법은 10 log_10 (P2/P1) 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;523&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbBhqu/btsGQ3biGHf/QyKiHbVroKTP60rPWKZIhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbBhqu/btsGQ3biGHf/QyKiHbVroKTP60rPWKZIhk/img.png&quot; data-alt=&quot;dB 측정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbBhqu/btsGQ3biGHf/QyKiHbVroKTP60rPWKZIhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbBhqu%2FbtsGQ3biGHf%2FQyKiHbVroKTP60rPWKZIhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;523&quot; height=&quot;217&quot; data-origin-width=&quot;523&quot; data-origin-height=&quot;217&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;dB 측정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 구간 P1, 출력 구간 P2의 세기를 통해 이 신호가 얼마나 감쇠했는지 확인할 수 있고, 중간에 증폭기(Amplifier)를 통해 신호의 세기를 증폭해 줄 수 있다. 실제로 리피터라는 통신 H/W로 신호를 증폭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;왜곡 (Distortion)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 진폭이 다른 1hz, 100hz 신호가 있다고 생각해보자. 전파의 특성상 주파수가 높을수록 곧게 직진하고 더 빠르다. 그래서 100hz 신호 전송이 1hz 신호 전송보다 빨리 끝날 수가 있게 된다. 이것을 주파수에 따른 지연 차이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 주파수가 높은 신호는 조금 더 짧아져서 원신호와 다른 모양이 나오게 되는 것이다. 이것을 주파수에 따른 지연 차이로 인한 위상 차이라고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 왜곡은 다른 주파수가 섞여 있는 복합신호에서 주파수에 따른 지연차이가 발생하고 그로 인해 위상차이가 발생하게 된다. 모든 신호를 수신하고 복합신호로 합치게 되면 위상차이로 인해 다른 파형이 만들어지는 현상을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IBIpf/btsGQ5z95il/1wdc2xB6CmmDFWCJ6PA9Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IBIpf/btsGQ5z95il/1wdc2xB6CmmDFWCJ6PA9Kk/img.png&quot; data-alt=&quot;주파수 지연에 따른 왜곡 현상&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IBIpf/btsGQ5z95il/1wdc2xB6CmmDFWCJ6PA9Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIBIpf%2FbtsGQ5z95il%2F1wdc2xB6CmmDFWCJ6PA9Kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;716&quot; height=&quot;287&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;주파수 지연에 따른 왜곡 현상&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;잡음 (Noise)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잡음은 신호에서 우리가 원치 않는 정보를 말하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Broadband Transmission에서 설명한 전송 장애의 예시가 잡음에 대한 설명이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잡음은 전송 과정에서 다른 신호와 합쳐지면서 신호의 왜곡이 발생하는 현상이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dropTW/btsGS8vFzbq/uHs0g8Z0QtSAGnilehjTH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dropTW/btsGS8vFzbq/uHs0g8Z0QtSAGnilehjTH0/img.png&quot; data-alt=&quot;Noise 현상&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dropTW/btsGS8vFzbq/uHs0g8Z0QtSAGnilehjTH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdropTW%2FbtsGS8vFzbq%2FuHs0g8Z0QtSAGnilehjTH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;232&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Noise 현상&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신호가 잡음에 대해 얼마나 영향을 받는지 확인하는 지표로 SNR(Signal-to-Noise Ratio)을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SNR = (신호의 세기) / (노이즈의 세기), SNR_dB = 10log_10(SNR)&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;하지만! 전송 장애는 거의 H/W 쪽에서의 문제이므로 H/W 나 Embedded 개발자가 될 것이 아니라면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만! 화상 채팅, 영상 처리, Discord 쪽의 방향을 생각한다면 필요하다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 데이터 속도와 연관있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용 가능한 대역폭 2. 신호 수준 3. 노이즈 수준 (채널 품질)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데이터 속도와 어떤 연관이 있을까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Nyquist bit rate&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나이퀴스트의 bit rate는 잡음이 없는 채널일 경우, 구할 수 있는 최대 bit rate를 구하는 공식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bit Rate = 2 * bandwidth(hz) * log_2(Siganl's Level)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 신호의 레벨이 높아질 수록 신뢰할 수 있는 정보는 줄어든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 그럴까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림 A를 보면 초 당 전달할 수 있는 bit 레벨이 높아질 수록 세분화해서 양자화를 진행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 실제 통신 과정에서 잡음이 발생할텐데 잡음이 생기면서 왜곡이 생긴다고 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레벨이 세분화 되어있을수록 왜곡으로 인해 원 신호와 더욱 바뀌게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Shannon's Capacity&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샤논의 용량은 잡음이 있는 채널일 경우, 구할 수 있는 최대 전송량을 구하는 공식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샤논은 실제 통신 과정에서 잡음은 무조건 있으므로 해당 공식을 제시하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 실제 Download 하거나 어떤 통신 장비의 속도 정보를 볼 때, 이 공식을 통해 얻게 된 정보이다.&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;Capacity = bandwidth(hz) * log_2(1+SNR)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대역폭마다 잡음이 없는 경우는 없으므로 만약의 잡음의 세기가 0이라서 SNR이 0이 나올 경우, 채널의 용량은 0이 된다. 즉, 존재할 수 없는 경우라는 뜻이다.&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;반대로 샤논의 용량을 통해 최대 용량을 구하게 됐으면 Nyquist 정리에 의해 신호의 Level도 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C = 4Mbps 이고 채널이 1Mhz 대역폭이라면, 2 * 1Mhz * log_2(L) 이므로 신호의 L은 4임을 알 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;통신 성능에 대한 정보&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 통신에서 성능을 결정 짓는 요소는 다양하게 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Bandwidth에서 가용해주는 주파수 범위&lt;/li&gt;
&lt;li&gt;네트워크를 통해 실제로 데이터를 전송할 수 있는 속도 (Throughput, Shannon과 연관)&lt;/li&gt;
&lt;li&gt;전파시간 + 전송시간 + 큐딜레이 시간 + 처리 시간을 칭하는 Latency(지연시간, Delay)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Transmission Time은 data size / bandwidth 가 된다.&lt;/li&gt;
&lt;li&gt;Queuing Time은 중간 목적지, 최종 목적지에서 데이터를 처리하기 위해 대기열에서 대기하는 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Bandwidth Delay Product
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;bandwidth의 길이가 목적지까지 도착하는 지연 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Jitter
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 상태에 따른 패킷의 우선순위 등 패킷마다 다른 지연시간을 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/데이터 통신</category>
      <category>BASEBAND</category>
      <category>Broadband</category>
      <category>CS</category>
      <category>nyquist</category>
      <category>Physical Layer</category>
      <category>shannon capacity</category>
      <category>데이터 통신</category>
      <category>디지털 신호</category>
      <category>물리 계층</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/60</guid>
      <comments>https://dev-dot.tistory.com/entry/4-Physical-Layer-Digital-Signals#entry60comment</comments>
      <pubDate>Wed, 24 Apr 2024 06:10:14 +0900</pubDate>
    </item>
    <item>
      <title>3. Physical Layer - Data와 Signals 그리고 Bandwidth</title>
      <link>https://dev-dot.tistory.com/entry/3-Physical-Layer-Data%EC%99%80-Signals</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;물리 계층에 대해 들어가기 전에 데이터와 신호에 대한 개념이 필요한가보다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 통신에서 데이터는 두 가지 종류가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 아날로그 데이터 - 연속적인 정보를 가지고 있는 데이터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 디지털 데이터 - 불연속적인 정보를 가지고 있는 데이터&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xBKRS/btsGQY01voM/N5KUBzkKNs1roBS4sGxN9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xBKRS/btsGQY01voM/N5KUBzkKNs1roBS4sGxN9K/img.png&quot; data-alt=&quot;그림 A. 아날로그 신호와 디지털 신호&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xBKRS/btsGQY01voM/N5KUBzkKNs1roBS4sGxN9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxBKRS%2FbtsGQY01voM%2FN5KUBzkKNs1roBS4sGxN9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;644&quot; height=&quot;166&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 A. 아날로그 신호와 디지털 신호&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아날로그 데이터와 디지털 데이터를 각 각 신호로 나타내면 그림 A처럼 표현할 수 있다.&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;각 신호는 주기적인 신호(Periodic)와 비주기적인 신호(Non-Periodic)로 구분할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주기적인 신호는 일정한 패턴이 동일한 시간 내 반복되는 것을 말하고 사이클을 형성한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비주기적인 신호는 시간이 지남에 따라 반복되는 패턴 없이 신호가 바뀌는 것을 말한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;151&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2OHJS/btsGPStin1z/rWePxdjsWrq6wepuat1A2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2OHJS/btsGPStin1z/rWePxdjsWrq6wepuat1A2k/img.png&quot; data-alt=&quot;그림 B. Sine 파&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2OHJS/btsGPStin1z/rWePxdjsWrq6wepuat1A2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2OHJS%2FbtsGPStin1z%2FrWePxdjsWrq6wepuat1A2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;490&quot; height=&quot;151&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;151&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 B. Sine 파&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 그림 B와 같은 정형파가 주기적인 신호에 속한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외, 그림 A와 같은 신호들은 비주기적인 신호라고 한다.&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;진폭, 주기, 주파수, 위상, propagation speed, wavelength 에 대한 내용은 따로 작성하지 않겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 신호 처리에 더 적합한 내용으로 판단.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VJBM4/btsGS5MljKm/vGkSo86RI6j86TKMoX8Zv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VJBM4/btsGS5MljKm/vGkSo86RI6j86TKMoX8Zv1/img.png&quot; data-alt=&quot;시간축과 주파수축&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VJBM4/btsGS5MljKm/vGkSo86RI6j86TKMoX8Zv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVJBM4%2FbtsGS5MljKm%2FvGkSo86RI6j86TKMoX8Zv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;836&quot; height=&quot;272&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시간축과 주파수축&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 신호는 시간 관점에서 측정한다. 하지만 주파수 관점에서 측정하면 전혀 다른 그래프를 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 주파수 관점에서 측정할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주파수 관점에서 측정하면 신호에서 얼만큼의 진폭을 가진 신호들이 얼마나 나타났는지 한 번에 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 시간 축에서 몇 개의 신호가 있었는지를 생각해보자. 1초 사이의 모든 신호의 개수를 세어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;639&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCmrPG/btsGSOxlddm/AKRG8SY8XICpdclWcTn79K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCmrPG/btsGSOxlddm/AKRG8SY8XICpdclWcTn79K/img.png&quot; data-alt=&quot;시간축과 주파수축 2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCmrPG/btsGSOxlddm/AKRG8SY8XICpdclWcTn79K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCmrPG%2FbtsGSOxlddm%2FAKRG8SY8XICpdclWcTn79K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;639&quot; height=&quot;390&quot; data-origin-width=&quot;639&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시간축과 주파수축 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;f의 한 주기를 1초라고 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1초 동안 f는 1주기를 가지고, 3f는 3주기, 9f는 9주기를 가진 것을 확인할 수 있다.&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;blockquote data-ke-style=&quot;style2&quot;&gt;대역폭 (Bandwidth)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 주파수 도메인 개념을 사용해서 비주기 신호에 대해서도 정확한 분석값을 측정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 축만 사용한다면 주기를 알 수 없어, 신호에 대한 예측이 불가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 주파수들만 관측할 수 있다면 주기를 몰라도 된다. 즉, 비주기 신호에 대해서도 예상 범위가 생긴 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rrLg9/btsGRf3uP7p/Kihmf6LIzXN2Q5ORFCZQIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rrLg9/btsGRf3uP7p/Kihmf6LIzXN2Q5ORFCZQIk/img.png&quot; data-alt=&quot;비주기 신호의 시간축과 주파수축&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rrLg9/btsGRf3uP7p/Kihmf6LIzXN2Q5ORFCZQIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrrLg9%2FbtsGRf3uP7p%2FKihmf6LIzXN2Q5ORFCZQIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;706&quot; height=&quot;252&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;비주기 신호의 시간축과 주파수축&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 주파수 도메인은 특정 주파수에 대한 신호만 필터링하는 역할로 사용할 수 있고 필터링 기준이 되는 것을 대역폭 (Bandwidth) 이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QVWQZ/btsGSPbUqyt/JHUBCnXNv87FrhoqcRBOPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QVWQZ/btsGSPbUqyt/JHUBCnXNv87FrhoqcRBOPk/img.png&quot; data-alt=&quot;그림 A. 특정 시스템의 Bandwidth&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QVWQZ/btsGSPbUqyt/JHUBCnXNv87FrhoqcRBOPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQVWQZ%2FbtsGSPbUqyt%2FJHUBCnXNv87FrhoqcRBOPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;575&quot; height=&quot;194&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 A. 특정 시스템의 Bandwidth&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 개인적으로 데이터 통신을 공부하면서 느낀 점이 Bandwidth가 참 중요하다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bandwidth를 제대로 이해하지 못해 뒤에서 생각이 많이 꼬였었다. 그래서 해당 포스트에서 Bandwidth에 대해 쉽게 이해할 수 있도록 설명하고 뒤에서 Bandwidth와 관련된 개념들을 더 자세히 작성할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Bandwidth는 고속도로다.&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;고속도로를 생각해보자. 고속도로를 통해 오토바이나 사람이나 자전거가 지나갈 수 있을까?&lt;span&gt;&amp;nbsp;&lt;/span&gt;철저히 금지하고 있다.&amp;nbsp; 마찬가지로 대역폭 또한 출발지에서 목적지로 가기 위한 신호를 철저히 관리한다. 그림 A를 확인한다면 1000 Hz ~ 5000 Hz 까지에 대한 대역폭이다. 그럼 1000hz부터 5000hz까지가 차량이 되고 1000 hz 미만은 오토바이, 자전거, 사람으로 생각한다. 반대로 5000 hz 초과는 비행기, 헬리콥터, 기차와 같은 것으로 생각하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;고속도로의 경우, 차량만 진입할 수 있도록 하겠다라는 대역폭이 있으면 통신에서는 1000 Hz ~ 5000 Hz까지의 신호만 진입할 수 있도록 하겠다는 대역폭이 있고 이 크기를 최대 신호 - 최소 신호 = 4000Hz로 나타낸다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 4000 Hz는 고속도로의 크기라고 생각하면 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Bandwidth의 각 차선은 Channel이다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번에서 4000 Hz의 너비를 가진 고속도로를 생성했다. 그럼, 실제 고속도로를 생각해보자. 차들은 각 차선에서 대열을 맞추면서 이동한다. 만약 차선 없이 뻥 뚫린 고속도로였다면 대열이 막 흐트러져 있을 것이고 차가 밀리는 일이 더 자주 발생할 것이다. 또, 특정 차선을 쭉 따라간다면 목적지에 도착할 수 있다는 보장이 있는데 차선이 없다면 중간에 어디로 이동해야하는지 모르게 된다. 그래서 각 차선에 버스 전용 차선, 화물차 전용 차선, 서울 방향 차선, 부산 방향 차선 등 약속을 해놓았다. 마찬가지로 대역폭에서도 목적지로 가기 위한 차선이 존재해야하고 그것을 통신에서는 Channel 이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통신에서는 TV Channel, Radio Channel 등 다양하게 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.mykit.com/kor/ele/freq.html&quot;&gt;참고 : https://www.mykit.com/kor/ele/freq.html&lt;/a&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 각 Channel도 Bandwidth가 존재한다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 부산에서 출발한다. 경부 고속도로에서 화물차 전용 차선을 따라 이동한다고 생각해보자. 특정 지점에서 경기도 방향으로 갈 것인지 서울 방향으로 갈 것인지 그에 맞추어서 이동하라는 이정표가 존재한다. 이것이 통신의 관점에서 보면 각 Channel의 Bandwidth이다. 대표적인 예시로 TV 채널이 있다. 우리가 TV를 보는데 1번 Channel을 볼 지 2번 Channel을 선택할 때 마다 다른 내용이 들어오는 것을 확인할 수 있다.&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;위 내용이 Bandwidth를 설명하기 가장 적합한 표현이라고 생각한다. 그리고 위 설명을 제대로 인지했다면 통신의 신호는 복합신호라는 것을 알게 될 것이다. TV를 본다고 생각해보자. TV Channel 번호에 따라 정보가 바뀐다면 Channel 번호를 선택하는 시점에 신호에서 필터링이 되고 있다는 것까지 알았다면 물리 계층을 매우 쉽게 이해할 수 있다.&lt;/p&gt;</description>
      <category>CS/데이터 통신</category>
      <category>bandwidth</category>
      <category>channel</category>
      <category>Computer science</category>
      <category>CS</category>
      <category>frequency</category>
      <category>대역폭</category>
      <category>데이터 통신</category>
      <category>신호</category>
      <category>주파수</category>
      <category>컴퓨터 공학</category>
      <author>  Laboon</author>
      <guid isPermaLink="true">https://dev-dot.tistory.com/59</guid>
      <comments>https://dev-dot.tistory.com/entry/3-Physical-Layer-Data%EC%99%80-Signals#entry59comment</comments>
      <pubDate>Tue, 23 Apr 2024 19:51:23 +0900</pubDate>
    </item>
  </channel>
</rss>