├── Algorithm ├── DP, 분할 정복, 그리디.md ├── Divide & Conquer.md ├── Graph.md ├── Readme.md ├── Sorting.md └── 완전탐색, 재귀.md ├── Data Structure ├── Array.md ├── Graph.md ├── Hash.md ├── Readme.md ├── Stack, Queue.md └── Tree & Heap.md ├── Database ├── Clustering, Replication.md ├── Database, key.md ├── Index.md ├── Normalization.md ├── Partitioning & Sharding.md ├── Readme.md └── sql query.md ├── Java ├── AccessModifier.md ├── CollectionFramework.md ├── Error & Exception.md ├── GC.md ├── Generic.md ├── JDK8.MD ├── JVM.md ├── Modifier.md ├── OOP.md ├── Readme.md ├── Synchronization.md └── Wrapper.md ├── Network ├── ApplicationLayer.md ├── Cookie, Session, OAuth, JWT.md ├── HTTP,HTTPS.md ├── Internet Layer (Network Layer).md ├── Network Access Layer (Physical & Data).md ├── PresentationLayer.md ├── REST API.md ├── Readme.md ├── SessionLayer.md ├── TCP, UDP.md ├── TransportLayer.md ├── 웹 접속 과정.md └── 웹서버, WAS.md ├── Operating System ├── CPU Sheduling.md ├── Cache Memory & Memory Layered.md ├── Context Switching & PCB.md ├── Critical Section.md ├── Deadlock.md ├── File System.md ├── Interrupt.md ├── Page Replacement Algorithm.md ├── Paging & Segmentation.md ├── Process.md ├── Readme.md ├── Synchronous & Asynchronous & blocking & nonblocking.md ├── TLB, MMU.md └── Virtual Memory.md └── README.md /Algorithm/DP, 분할 정복, 그리디.md: -------------------------------------------------------------------------------- 1 | # DP 2 | - DP란 **복잡한 문제를 간단한 여러 개의 문제로 나누어 푸는 방법**을 말합니다. DP에서는 2가지 조건을 충족해야 만 사용이 가능합니다. 3 | 1. **부분 반복 문제**(Overlapping Subproblem) 4 | - 어떤 문제가 여러 개의 부분 문제로 쪼개질 수 있는 경우를 말합니다. 5 | 2. **최적 부분 구조**(Optimal Substructure) 6 | - 작은 부분 문제에서 구한 최적의 답으로 큰 문제를 해결할 수 있는 경우를 말합니다. 7 | 8 | 이때, 분할 정복과의 가장 큰 차이는 **분할 정복법은 작은 문제의 답이 달라질 수 있지만, DP는 그렇지 않다는 것**입니다. 9 | 10 | - DP를 구현 할 때에는 **Memoization**과 **Tabulation**을 사용해서 구현이 가능합니다. 11 | 1. **Memoization** 12 | - 13 | 14 | - 재귀를 이용해서 문제를 해결 할 경우에 사용하는 테이블, **Top-Bottom** 으로 해결 할 경우 사용 15 | 2. **Tabulation** 16 | 17 | ![Image](https://nulls.co.kr/media/post-body/2021/11/11/image_NfyGvHQ.png) 18 | - 반복문을 이용해서 문제를 해결 할 경우에 사용하는 테이블, **Bottom-Up**으로 해결 할 경우 사용 19 | 20 | #### Q) DP의 2가지 조건에 대해서 설명해주세요. 21 | - 어떤 문제가 여러 개의 부분 문제로 쪼개질 수 있는 경우인 **부분 반복 문제**를 충족해야 하고, 작은 부분 문제에서 구한 최적의 답으로 큰 문제를 해결할 수 있다는 **최적 부분 구조** 를 충족해야 합니다. 22 | 23 | #### Q) Top-Bottom 방식과 Bottom-Up 방식의 장단점에 대해서 설명해주세요. 24 | - **Top-Bottom** 25 | **[장점]** : 재귀를 이용한 방식이기 때문에 **가독성이 좋고, 서브 문제를 해결 할 경우 필요한 서브 문제들만 해결해도 된다는 장점**이 있습니다. 26 | **[단점]** : 결과가 어떻게 나오는지 알고 있어야 하며, **저수준으로 갈 수록 복잡해질 수 있으며, 리소스의 사용이 많아질수 있다**는 문제가 있습니다. 27 | 28 | - **Bottom-UP** 29 | **[장점]** : **처리 시간과 리소스 사용을 줄일 수 있고, 점화식을 찾은 경우에 점화식을 이용하여 문제를 해결 할 수 있다는 장점**이 있습니다. 30 | **[단점]** : 반복문으로 진행하다보니 **재귀 방식에 비해서 구현이 복잡** 할 수 있으며, Top-Bottom은 대 문제를 해결하기 위해 필요한 소 문제에 대해서만 구현을 하면 되지만 Bottom-Up 방식은 **처음부터 해결해야 하는 대문제까지의 모든 경우를 구해야 한다**는 단점이 있습니다. 31 | 32 | --- 33 | # Divide & Conquer (분할 정복) 34 | * 문제를 나눌 수 없을 때까지 나누어서 각각을 풀면서 다시 합병하여 문제의 답을 얻는 알고리즘입니다. 35 | - **하향식 접근법** 으로, 상위의 해답을 구하기 위해, 아래로 내려가면서 (top-down) 하위의 해답을 구하는 방식으로 수행됩니다. 36 | - 일반적으로 재귀함수로 구현합니다. 37 | > **divide-and-conquer의 핵심은 재귀호출입니다.** 38 | - Divide & Conquer은 `top-down` 접근 방식을 사용합니다. 39 | - 이때 문제를 잘게 쪼갤 때, 부분 문제는 서로 중복되지 않습니다. top-down이란, 처음부터 큰 문제를 방문 후 작은 문제를 호출, 재귀(recursive)방식을 사용합니다. 40 | (ex) 병합 정렬, 퀵 정렬 등 41 | 42 | #### 분할 정복 용어 43 | - Divide : 문제를 더 작은 문제로 분할하는 과정 44 | - Merge : 각 문제에 대해 구한 답을 원래 문제에 대한 답으로 병합하는 과정(merge) 45 | - Base case : 더 이상 답을 분할하지 않고 곧장 풀 수 있는 매우 작은 문제 46 | 47 | ### Q) 분할정복의 장단점을 설명해주세요 48 | - 장점 : 큰 문제를 재귀적으로 나누어 해결하기에 간단하지만 빠르며 병렬적으로 문제를 해결할 수 있다는 장점이 있습니다. 49 | - 단점 : 재귀적으로 문제를 해결하기 때문에 인풋이 너무 큰 경우 많은 프로그래밍 언어에서 Stack Overflow가 발생할 수 있으며, 이는 메모리의 비효율적 사용을 야기할 수 있습니다. 50 | 51 | ### Q) DP와 분할 정복의 공통점과 차이점을 설명해주세요 52 | 53 | **DP와 분할 정복의 공통점** 54 | - 문제를 잘게 쪼개서, 가장 작은 단위로 분할한다는 것입니다. 55 | 56 | **DP와 분할 정복의 차이점** 57 | 58 | 1) **동적 계획법** 59 | - DP의 부분 문제는 중복되기에 상위 문제 해결 시 재활용됩니다. 따라서 DP는 서로 상관관계가 있는 문제를 해결하는데에 적합합니다. 60 | - Memoization 기법을 사용합니다.(부분 문제의 해답을 저장해서 재활용하는 최적화 기법으로 사용) 61 | 62 | 2) **분할 정복** 63 | - 분할정복의 부분 문제는 서로 중복되지 않습니다. 따라서 분할정복은 서로 상관관계가 없는, 쪼개진 결과가 서로 독립적인 성격의 문제를 해결하는데 적합합니다. 64 | - Memoization 기법을 사용하지 않습니다. 65 | 66 | --- 67 | 68 | # Greedy 69 | - 그리디란 **미래를 생각하지 않고 현재 단계에서 가장 최선의 선택을 하는 기법**입니다 . 순간마다 하는 선택은 그 순간에 대해 지역적으로 최적이지만, 모았을 때 그것이 **최적의 해라는 보장은 없습니다.** 70 | - 그리디로 해결이 안되는 상황을 예시로 설명해보겠습니다. 지금 선택하면 1개의 쿠키를 받고, 1분 기다렸다 선택하면 2개의 쿠키를 받는 문제 가 있을 때 지금 **당장 최선의 선택은 쿠키 1개**를 받는 거지만, **결과적으로는** 1분 기다렸다가 **2개 받는 선택이 최선**입니다. 71 | 72 | ### Q) 그리디와 DP의 차이점에 대해 말씀해주세요. 73 | 문제를 작은 문제로 분할하여 해결하거나, 부분 문제의 최적해를 활용해 전체 문제의 최적해를 구한다는 문제 해결 방식은 동일합니다. 74 | 하지만 그리디는 **각 단계에서 최선의 선택을 하기 때문에 현재 선택이 나중에 영향을 끼친다**면 이는 최적의 해를 보장할 수 없습니다. 따라 이런 경우에는 **DP**, 영향을 끼치지** 않을 때 그리디**를 사용합니다. 75 | 76 | ### Q) 속도 측면에서는 뭐가 더 우세할까요? 77 | **그리디 알고리즘**입니다. 78 | **동적 프로그래밍 알고리즘**은 중복 계산을 피하고 전역적인 최적해를 보장하기는 하지만, **메모리 공간을 많이 사용**하고, 부분 문제들의 결과를 계산하고 저장하는 과정이 복잡하기 때문에 일반적으로 **그리디 알고리즘보다 더 높은 시간복잡도**를 가질 수 있습니다. 79 | 80 | --- 81 | 82 | 83 | Untitled-3 84 | 85 | ### 참고 86 | DP 87 | [이미지 출처](https://nulls.co.kr/codeit/392) 88 | 89 | 90 | 분할정복 91 | [이미지&내용 출처](https://syujisu.tistory.com/entry/%EB%8F%99%EC%A0%81-%EA%B3%84%ED%9A%8D%EB%B2%95-Dynamic-Programming%EA%B3%BC-%EB%B6%84%ED%95%A0-%EC%A0%95%EB%B3%B5-Divide-and-Conquer-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98) 92 | 93 | [이미지&내용 출처](https://korguy.tistory.com/entry/%EB%B0%A9%EB%B2%95%EB%A1%A0-Divide-and-Conquer-%EB%B6%84%ED%95%A0%EC%A0%95%EB%B3%B5) 94 | 95 | 그리디 96 | [이미지 출처](https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Algorithm) 97 | -------------------------------------------------------------------------------- /Algorithm/Divide & Conquer.md: -------------------------------------------------------------------------------- 1 | # Divide & Conquer (분할 정복) 2 | * 문제를 나눌 수 없을 때까지 나누어서 각각을 풀면서 다시 합병하여 문제의 답을 얻는 알고리즘입니다. 3 | - **하향식 접근법** 으로, 상위의 해답을 구하기 위해, 아래로 내려가면서 (top-down) 하위의 해답을 구하는 방식으로 수행됩니다. 4 | - 일반적으로 재귀함수로 구현합니다. 5 | > **divide-and-conquer의 핵심은 재귀호출입니다.** 6 | - Divide & Conquer은 `top-down` 접근 방식을 사용합니다. 7 | - 이때 문제를 잘게 쪼갤 때, 부분 문제는 서로 중복되지 않습니다. top-down이란, 처음부터 큰 문제를 방문 후 작은 문제를 호출, 재귀(recursive)방식을 사용합니다. 8 | (ex) 병합 정렬, 퀵 정렬 등 9 | 10 | #### 분할 정복 용어 11 | - Divide : 문제를 더 작은 문제로 분할하는 과정 12 | - Merge : 각 문제에 대해 구한 답을 원래 문제에 대한 답으로 병합하는 과정(merge) 13 | - Base case : 더 이상 답을 분할하지 않고 곧장 풀 수 있는 매우 작은 문제 14 | 15 | ### Q) 분할정복의 장단점을 설명해주세요 16 | - 장점 : 큰 문제를 재귀적으로 나누어 해결하기에 간단하지만 빠르며 병렬적으로 문제를 해결할 수 있다는 장점이 있습니다. 17 | - 단점 : 재귀적으로 문제를 해결하기 때문에 인풋이 너무 큰 경우 많은 프로그래밍 언어에서 Stack Overflow가 발생할 수 있으며, 이는 메모리의 비효율적 사용을 야기할 수 있습니다. 18 | 19 | ### Q) DP와 분할 정복의 공통점과 차이점을 설명해주세요 20 | 21 | **DP와 분할 정복의 공통점** 22 | - 문제를 잘게 쪼개서, 가장 작은 단위로 분할한다는 것입니다. 23 | 24 | **DP와 분할 정복의 차이점** 25 | 26 | 1) **동적 계획법** 27 | - DP의 부분 문제는 중복되기에 상위 문제 해결 시 재활용됩니다. 따라서 DP는 서로 상관관계가 있는 문제를 해결하는데에 적합합니다. 28 | - Memoization 기법을 사용합니다.(부분 문제의 해답을 저장해서 재활용하는 최적화 기법으로 사용) 29 | 30 | 2) **분할 정복** 31 | - 분할정복의 부분 문제는 서로 중복되지 않습니다. 따라서 분할정복은 서로 상관관계가 없는, 쪼개진 결과가 서로 독립적인 성격의 문제를 해결하는데 적합합니다. 32 | - Memoization 기법을 사용하지 않습니다. 33 | 34 | #### 사진 & 내용 출처 35 | 36 | https://syujisu.tistory.com/entry/%EB%8F%99%EC%A0%81-%EA%B3%84%ED%9A%8D%EB%B2%95-Dynamic-Programming%EA%B3%BC-%EB%B6%84%ED%95%A0-%EC%A0%95%EB%B3%B5-Divide-and-Conquer-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98 37 | 38 | https://korguy.tistory.com/entry/%EB%B0%A9%EB%B2%95%EB%A1%A0-Divide-and-Conquer-%EB%B6%84%ED%95%A0%EC%A0%95%EB%B3%B5 39 | 40 | -------------------------------------------------------------------------------- /Algorithm/Readme.md: -------------------------------------------------------------------------------- 1 | ### 알고리즘 2 | -------------------------------------------------------------------------------- /Algorithm/완전탐색, 재귀.md: -------------------------------------------------------------------------------- 1 | # 완전탐색 2 | 가능한 모든 경우를 탐색하는 기법입니다. 완전탐색 기법 중 하나인 백트래킹과 DFS를 예시로 설명해보겠습니다. 3 | 4 | ### 백트레킹(backtracking) 5 | - 답을 찾아가다 불필요한 경우 (즉 답이 나올 수 없는 경우)에 그 경로를 탐색하지 않고 되돌아가는 방식을 말합니다. 불필요한 부분을 쳐낸다는 점에서 가지치기라고도 표현할 수 있습니다. 6 | - 주로 DFS로 모든 경우를 탐색하는 과정에서, 조건문을 걸어 답이 될 수 없는 상황엔 탐색을 중지하는 하도록 구현할 수 있습니다. 7 | 8 | ### Q) 완전탐색을 구현하는 방식을 재귀로도 구현할 수 있는데, 재귀에 대해 설명해주세요. 9 | - 함수가 자기 자신을 호출하는 것을 의미합니다. 즉, 함수가 실행 도중에 자기 자신을 호출하여 문제를 해결하는 방식입니다. 10 | 11 | ### Q-1) 재귀함수를 구현할 때 필수조건에 대해 설명해주세요. 12 | 값을 찾을 때, 중단 조건을 명시해줘야 합니다. 중단 조건이 충족되면 재귀가 종료되고, 함수가 호출된 순서대로 결과를 반환하여 문제를 해결합니다 13 | 14 | ### Q) 완전탐색의 재귀와 DP는 큰 문제를 잘게 쪼갠다는 공통점이 있는데, 차이점은 뭘까요? 15 | - 메모이제이션 입니다. 16 | - 완전탐색은 중복된 부분 문제를 다시 계산합니다. 즉, 같은 부분 문제를 여러 번 해결하게 될 수 있습니다. 17 | - 반면에 DP는 중복된 부분 문제를 한 번만 계산하고 그 결과를 메모이제이션(Memoization)이나 테이블에 저장하여 재활용합니다. 이를 통해 계산의 중복을 피하고 실행 시간을 줄일 수 있습니다. 18 | 19 | ### Q) 완전탐색을 하게 되는 경우 여러 조건이 있는데 중복이 존재 여부/ 순서 존재 여부 의 4가지 경우의 시간복잡도에 대해 설명해주세요. 20 | > 💡 Hint! 순열, 조합, 중복순열, 중복조합 21 | 완전탐색 최악 시간 복잡도 O(N^M) 22 | 23 | 24 | 25 | **1. 순열 : 순서O, 중복X** 26 | - 서로 다른 n개에서 r개를 뽑아서 정렬하는 경우의 수 27 | - 중첩된 반복문을 사용하여 가능한 모든 순열을 생성하므로, 시간복잡도가 매우 크게 증가 28 | - 시간복잡도 `O(nPr) = O(n! / (n-r)!)` 29 | 30 | 31 |
32 | 순열 JAVA 코드 33 | 34 | 35 | 36 | ```java 37 | void permutation(int[] arr, int r) { 38 | int[] result = new int[r]; 39 | boolean[] used = new boolean[arr.length]; 40 | permutationUtil(arr, r, result, used, 0); 41 | } 42 | 43 | void permutationUtil(int[] arr, int r, int[] result, boolean[] used, int depth) { 44 | if (depth == r) { 45 | // 순열 결과 출력 또는 처리 46 | return; 47 | } 48 | 49 | for (int i = 0; i < arr.length; i++) { 50 | if (!used[i]) { 51 | used[i] = true; 52 | result[depth] = arr[i]; 53 | permutationUtil(arr, r, result, used, depth + 1); 54 | used[i] = false; 55 | } 56 | } 57 | } 58 | ``` 59 | 60 | 61 | 62 |
63 | 64 | 65 | 66 | **2. 중복순열 : 순서O, 중복O** 67 | - 서로 다른 n개에서 중복이 가능하게 r개를 뽑아서 정렬하는 경우의 수 68 | - 중첩된 반복문을 사용하여 가능한 모든 순열을 생성하므로, 시간복잡도가 매우 크게 증가 69 | - 시간복잡도 `O(n^r)` 70 | 71 | 72 |
73 | 중복 순열 JAVA 코드 74 | 75 | 76 | 77 | ```java 78 | void duplicatePermutation(int[] arr, int r) { 79 | int[] result = new int[r]; 80 | duplicatePermutationUtil(arr, r, result, 0); 81 | } 82 | 83 | void duplicatePermutationUtil(int[] arr, int r, int[] result, int depth) { 84 | if (depth == r) { 85 | // 중복 순열 결과 출력 또는 처리 86 | return; 87 | } 88 | 89 | for (int i = 0; i < arr.length; i++) { 90 | result[depth] = arr[i]; 91 | duplicatePermutationUtil(arr, r, result, depth + 1); 92 | } 93 | } 94 | ``` 95 | 96 | 97 | 98 |
99 | 100 | 101 | 102 | 103 | **3. 조합 : 순서X, 중복X** 104 | - 서로 다른 n개에서 순서 없이 r개를 뽑는 경우의 수 105 | - 재귀적으로 모든 조합을 생성하며, 중첩된 반복문을 사용하지 않기 때문에, 시간복잡도가 일반적으로 순열보다 작음 106 | - 시간복잡도 ` O(nCr) = O(n! / ((n-r)! * r!))` 107 |
108 | 조합 JAVA 코드 109 | 110 | 111 | 112 | ```java 113 | void combination(int[] arr, int r) { 114 | int[] result = new int[r]; 115 | combinationUtil(arr, r, result, 0, 0); 116 | } 117 | 118 | void combinationUtil(int[] arr, int r, int[] result, int depth, int start) { 119 | if (depth == r) { 120 | // 조합 결과 출력 또는 처리 121 | return; 122 | } 123 | 124 | for (int i = start; i < arr.length; i++) { 125 | result[depth] = arr[i]; 126 | combinationUtil(arr, r, result, depth + 1, i + 1); 127 | } 128 | } 129 | ``` 130 | 131 | 132 | 133 |
134 | 135 | 136 | 137 | 138 | **4. 중복조합 : 순서X, 중복O** 139 | - 서로 다른 n개에서 순서 없이, 중복이 가능하게 r개를 뽑는 경우의 수 140 | - 중첩된 반복문을 사용하여 가능한 모든 조합을 생성하므로, 시간복잡도가 중복 순열보다 크게 증가 141 | - 시간복잡도 `O((n+r-1)Cr) = O(((n+r-1)!)/((n-1)! * r!))` 142 | 143 | 144 |
145 | 중복 조합 JAVA 코드 146 | 147 | 148 | 149 | ```java 150 | void duplicateCombination(int[] arr, int r) { 151 | int[] result = new int[r]; 152 | duplicateCombinationUtil(arr, r, result, 0, 0); 153 | } 154 | 155 | void duplicateCombinationUtil(int[] arr, int r, int[] result, int depth, int start) { 156 | if (depth == r) { 157 | // 중복 조합 결과 출력 또는 처리 158 | return; 159 | } 160 | 161 | for (int i = start; i < arr.length; i++) { 162 | result[depth] = arr[i]; 163 | duplicateCombinationUtil(arr, r, result, depth + 1, i); // 중복이 허용되므로 i+1 대신 i를 전달 164 | } 165 | } 166 | ``` 167 | 168 | 169 | 170 |
171 | -------------------------------------------------------------------------------- /Data Structure/Array.md: -------------------------------------------------------------------------------- 1 | # 배열 2 | 배열이란, **동일한 자료형을 연속된 메모리 공간에 할당**하는 자료구조입니다. 3 | 연속된 공간에 저장되기 때문에, **0부터 시작하는 인덱스**를 통해 **값에 빠르게 접근**할 수 있다는 `O(1)` 장점이 있는 반면, 4 | 값을 **삽입/삭제** 하는 경우, 그 뒤의 **모든 요소들을 shift 하기 때문에 `O(N)` 비효율적**이라는 단점이 있습니다. 5 | 6 | ### Q) 배열과 리스트의 차이점에 대해 설명해주세요. 7 | 배열 : 초기 선언 시 **크기를 선언**하고, 크기 수정이 불가능합니다. (**고정적**) 8 | 리스트 : 초기 선언 시 크기를 **선언할 필요가 없고**, 크기가 **가변적** 입니다. 9 | 10 | ### Q-1) ArrayList와 LinkedList의 차이점 11 | **ArrayList** : **데이터를 연속적으로 저장**하기 때문에 12 | - 접근 `O(1)` : 인덱스를 통해 13 | - 삽입/삭제 `O(N)` : 뒤 shift 14 | 15 | **LinkedList** : **연속적인 공간에 저장하지 않고**, **각 노드가 데이터와 포인터**를 가지고 **포인터를 통해** 이전 노드와 다음 노드를 **연결**하기 때문에 16 | - 접근 `O(N)` : 순차적으로 탐색하며 접근 17 | - 삽입/삭제 `O(1)` : 앞뒤 링크만 변경 18 | 19 | ### Q-2) 배열과 리스트 둘 중 캐시의 지역성을 활용하기 좋은 건 뭘까요? (배열은 연속적으로 저장, 리스트는 불연속적으로 저장) 20 | - 배열입니다. 캐시의 지역성이란, 데이터 접근이 시간적 혹은 공간적으로 가깝게 일어나는 것을 의미합니다. **배열은 연속적으로 값을 저장하기 때문에, 특정 값에 접근하였을 때 주변 값에 빠르게 접근**할 수 있습니다. 이는 캐시의 지역성 중 공간적 지역성이 더 좋다고 표현할 수 있습니다. 21 | 22 | > 시간적 지역성 : 최근에 참조된 주소의 내용은 곧 다음에 다시 참조되는 특성 23 | 반복문 사용 시, 시간적 지역성이 좋다고 할 수 있습니다? 24 | 25 | 26 | ### Q) 배열같은 경우, index로 읽기에 속도가 빠르지만 검색 시 속도가 느립니다. 빠르게 검색할 수 있는 방법이 있을까요? 27 | - 첫번째 답 : 배열의 경우 순차적으로 접근하기 때문에 매번 O(N)의 시간 복잡도가 소요됩니다. 28 | 하지만 **HashMap을 사용하여 값을 저장한다면 O(N)의 시간 복잡도로 저장**하고, 이후에는 매번 **O(1)의 시간으로 값**을 찾을 수 있습니다. 29 | 30 | **Q-1) 배열을 첫번째부터 다 돌면서 HashMap에 저장하면 괜찮을까요?** 31 | - 비효율적 32 | 33 | 답 : **Binary Search** OR **선형 검색** 34 | 35 | --- 36 | > ### 종운님 추가조사👍 이진 탐색은 현업에서 거의 사용하지 않고, Hash 를 사용한다고 합니다. 37 | 이진 탐색을 하게 되면 결국 정렬 과정을 통해 선형 탐색보다 느리게 됩니다. ( 대부분의 데이터들은 정렬되지 않은 상태로 들어오므로 ) 38 | 이에 **이진 탐색을 사용하게 되면 선형 탐색보다 빠르다는 보증이 없습니다.** 39 | 데이터 삽입/삭제가 빈번한 실무에서는 추가될 때 마다 정렬하는 과정을 거쳐야 하므로 **이진탐색은 비효율적**입니다. 40 | 41 | 42 | 43 | --- 44 | 45 | 1. Binary Search (이진 탐색 알고리즘) : 원하는 값을 찾고 싶을 때, 정렬된 리스트에서 검색 범위를 줄여 나가며 검색 값을 찾는 알고리즘입니다. - 정렬된 리스트에만 사용할 수 있다는 단점이 있지만, 검색이 반복될 때 마다 검색 범위가 절반으로 줄어들기 때문에 속도가 빠르다는 장점이 있습니다. 46 | 47 | - 사용 방법 48 | - 처음에 N개 크기의 배열에서 단계가 하나씩 지나감에 따라 탐색할 배열의 크기를 반씩 줄입니다. 49 | 50 | - 이진 탐색을 사용하는 경우 시간복잡도 51 | - 정렬되어 있지 않은 상태 : `O(NlogN)` (정렬) , `O(logN)` (값 탐색) 52 | - 정렬된 상태 : `O(logN)` 53 | 54 | 2. 선형 탐색 : 일렬로 된 자료를 왼쪽부터 오른쪽으로 차례대로 탐색하는 것 55 | - 매번 O(N) 56 | 57 | **정리** 58 | - HashMap : O(N) 저장, 이후 O(1) 59 | - Binary Search, 정렬X : O(NlogN) 정렬, 이후 O(logN) 60 | - Binary Search, 정렬O : O(logN) 61 | - 선형검색 : 매번 O(N) 62 | 63 | ### Q) 배열 내의 중복된 값이 존재하는 지 찾는 방법에 대해 설명해주세요. 64 | 요약: 배열은 `O(N^2)`의 시간복잡도가 소요되기 때문에, 중복요소를 저장하지 않는 **HashSet 자료구조를 사용**하여 `O(N)`의 시간복잡도로 값을 저장한 후 **HashSet과 배열의 크기를 비교**하면 됩니다. 65 | 66 | --- 67 | 68 | 배열은 값을 순차적으로 저장하기 때문에, 중복여부를 판단할 수 없습니다. 따라서 2중 반복문을 통해 판단하면 `O(N^2)`의 시간복잡도가 소요됩니다. 69 | ```java 70 | for (int i = 0; i < arr.length; i++) { 71 | for (int j = i + 1; j < arr.length; j++) { 72 | if (arr[i] == arr[j]) { 73 | return true; // 중복 값 발견 74 | } 75 | } 76 | } 77 | ``` 78 | 79 | 이를 효율적으로 검색하기 위해, 중복 요소를 허용하지 않는 HashSet 자료구조를 사용하면 됩니다. `O(N)`의 시간복잡도로 배열의 크기인 N만큼 HashSet에 추가한 뒤, HashSet의 크기와 배열의 크기를 비교하여 알아낼 수 있습니다. 80 | - `HashSet.size() == Array.size()` : 중복요소 없다 81 | - `HashSet.size() != Array.size()` : 중복요소 있다 82 | ```java 83 | public static boolean hasDuplicates(int[] arr) { 84 | HashSet set = new HashSet(); 85 | for (int i = 0; i < arr.length; i++) { 86 | if (!set.add(arr[i])) { 87 | return true; // 중복 값 발견 88 | } 89 | } 90 | return false; // 중복 값 없음 91 | } 92 | ``` 93 | 94 | ### Q) list와 set을 비교해주세요. 95 | 💡 Hint! 중복과 순서 보장 96 | - List : 중복 허용 O, 순서 보장 O 97 | - Set : 중복 허용 X, 순서 보장 X 98 | 99 | ### Q-1) List와 Set을 사용하는 경우에 대해 설명해주세요. 100 | 💡 Hint! A라는 친구가 집단안에 있는 지 확인하고 싶은 경우, 어떤 자료구조를 사용할까요? 101 | - Set 입니다. contains 메소드를 통해 `O(1)`의 시간복잡도로 확인할 수 있습니다. 102 | - list 는 O(n)의 시간 복잡도가 걸리기 때문에, set을 사용하는 것이 효율적입니다. 103 | 104 | ✔️ List : 저장되는 데이터의 순서를 보장해야 할 때 105 | - 대기자 명단을 작성할 때 106 | 107 | 108 | 109 | ✔️ Set : 데이터가 존재하는 지 확인하고 싶을 때 110 | - 연락처 목록을 저장할 때 111 | 112 | ### Q) 배열의 softCopy와 deepCopy 에 대해 설명해주세요. 113 | 요약 : 자바의 객체와 같은 참조 변수는 직접 값을 저장하는 게 아닌 **힙 영역에 데이터를 저장하고 그의 주소값을 저장**하는 식으로 구성되어 있습니다. **softCopy**는 복사한 배열이 원래 배열의 **'주소값'을** 가져오고, **deepCopy는 '데이터'를** 가져옵니다. 114 | 115 | --- 116 | image 117 | 118 | 설명을 위해 arr1 과 arr2 배열을 예시로 설명해보겠습니다. 119 | arr1 의 값을 arr2에 복사하고 싶을 때, **`arr2 = arr1`는 softCopy** 입니다. (주소값만 복사, 같은 힙의 데이터를 바라봄) 120 | 121 | - arr2에 arr1의 `O(1)`의 시간복잡도로 모든 값이 복사됩니다. 하지만 이는 **배열의 주소값이 복사된 것으로, 메모리에서 동일한 배열을 참조**합니다. 따라서 **arr1 또는 arr2 의 값을 변경하게 되면, 동시에 변경**됩니다. 122 | 123 | 반면 **`arr2 = arr[1].clone();` 이나 `System.arrayCopy(arr1, 0, arr2, 0, arr1.length)` 는 deepCopy** 입니다. (원본이 참조하고 있는 힙의 데이터까지 복제) 124 | 125 | - 이는 **배열 자체가 완벽하게 새 배열에 복사**됩니다. 전체 요소를 복사하기 때문에 `O(N)`의 시간복잡도가 소요됩니다. 126 | 127 | 128 | > System.arraycopy() 129 | - 배열의 일부분을 다른 배열로 복사할 때 사용 130 | 131 | > clone() 주의 사항 132 | 133 | 1차원 배열, 단일 클래스 타입의 경우, clone()은 완벽히 다른 데이터를 참조합니다. 134 | **하지만 클래스 타입을 여러개 담고 있는 배열**을 복사하는 경우, 135 | - 참조 객체인 배열 자체는 완벽히 복사가 됩니다. 136 | - 하지만 **배열 내용물 객체**는 **얕은 복사**가 됩니다. 137 | - 원본과 복사본의 배열 요소가 담고있는 주소값이 같아 바라보는 힙 데이터가 같습니다. 138 | 139 | 이는 클래스를 복사할 경우, **clone()을 오버라이딩하여 재정의** 해줘야 합니다. 140 | 141 | ### Q) 배열을 정렬하는 경우, 어떤 알고리즘을 사용하는 경우 가장 효율적일까요? 142 | - `O(NlogN)`의 시간복잡도를 가진 병합 정렬, 퀵 정렬을 사용합니다. 143 | 144 | **자바 Arrays.sort()** 145 | - primitive(기본형) 타입의 배열인 경우 146 | - 듀얼피봇 퀵정렬(Dual-Pivot QuickSort)를 사용 147 | - 듀얼피봇 퀵정렬은 일반적인 퀵정렬과는 다르게 피봇을 2개를 두고 3개의 구간을 만들어 퀵정렬을 진행한다고 합니다. 이 정렬방식은 랜덤 데이터에 대해서 평균적으로 퀵소트 보다 좋은 성능을 낸다고 알려져있습니다. 148 | 149 | - reference(참조) 타입의 배열인 경우 150 | - 참조 타입의 배열인 경우는 TimSort를 사용 151 | 152 | **자바 Collections.sort()** 153 | - TimSort 사용 154 | - TimSort : 삽입(Insertion) 정렬과 합병(Merge) 정렬을 결합하여 만든 정렬 155 | 156 | ![image](https://user-images.githubusercontent.com/67494004/230757748-e2255865-ab32-4c70-9484-a84433d0d267.png) 157 | 158 | > Arrays를 정렬했을때와 Collections를 정렬했을때 왜 사용하는 알고리즘이 다른걸까요 ? 159 | (출처 : https://sabarada.tistory.com/138) 160 | 그 이유는 바로 참조 지역성 원리(Local of Reference)에 있습니다. 참조 지역성의 원리란 동일한 값 또는 해당 값의 근처에 있는 스토리지 위치가 자주 액세스되는 특성을 말합니다. 이 참조 지역성의 원리는 CPU의 캐싱 전략에 영항을 미칩니다. 즉, CPU가 데이터를 엑세스하며 해당 데이터만이 아니라 인접한 메모리에 있는 데이터 또한 캐시 메모리에 함께 올려둡니다. 161 | 162 | 정렬의 실제 동작 시간은 C * 시간복잡도 + a라고 합니다. 시간복잡도는 다 아시는 내용일 것이고 a 상대적으로 무시할 수 있습니다. 하지만 곱해지는 C의 영향도는 고려를 해야합니다. 생각하지 않을 수 없습니다. 이 C라는 값이 바로 참조 지역성 원리가 영향을 미칩니다. 163 | 164 | Array는 메모리적으로 각 값들이 연속적인 주소를 가지고 있기 때문에 C의 값이 낮습니다. 그래서 참조 지역성이 좋은 퀵 정렬을 이용하면 충분한 성능을 제공할 수 있다고 합니다. 하지만 Collection은 List를 기준으로 봤을때 메모리간 인접한 ArrayList 뿐만 아니라 메모리적으로 산발적인 LinkedList도 함께 존재합니다. 따라서 참조 인접성이 좋지 않고 C의 값이 상대적으로 높다고 합니다. 이럴 때는 퀵 정렬 보다는 합병정렬과 삽입정렬을 병합한 Tim 정렬을 이용하는게 평균적으로 더 좋은 성능을 기대할 수 있다고합니다. 165 | 166 | 167 | 168 | ### Q) Map 에 대해 설명해주세요. 169 | - Map은 Key(키)와 Value(값)으로 나눠 데이터를 관리합니다. 170 | - HashMap 을 예시로 설명한다면, 해시테이블에 요소가 저장되어, 검색 시 `O(1)`의 시간 복잡도로 탐색할 수 있습니다. 171 | - TreeMap 은 트리 구조로 저장되어, 요소 간 순서 보장이 필요할 때 `O(logN)` 의 시간복잡도로 탐색할 수 있습니다. 172 | 173 | ### Q-1) Key 중복이 되나요? 174 | - 중복이 허용되지 않습니다. 175 | 176 | ### Q) Hash가 저장되는 방식에 대해 설명해주세요. 177 | - key값과 value값이 들어오면 **Key값이 Hash Function을 통해 고정된 길이의 hash로 변경**됩니다. 이 Hash가 저장위치가 되어, value값을 저장합니다. 178 | 179 | - Hash Function 180 | Input : Key, Output : Hash 181 | key -- Hash Funtion(key) -- Hashing ... -> 고정된 길이의 hash 182 | 183 | ### Q) 배열은 선형 자료구조일까요, 비선형 자료구조일까요? 184 | - **선형 자료구조** 입니다. 선형 자료구조는 **한 원소 뒤에 하나의 원소만이 존재하는 형태로 자료들이 선형으로 나열되어 있는 구조**입니다. 이는 **배열, 리스트, 큐, 스택 등**이 해당됩니다. 185 | - 반대로 **비선형 자료구조**는 **한 원소에 대해 다대다 관계**로 계층적 구조를 표현하는데 사용됩니다. 이는 **트리, 그래프** 등이 포함됩니다. 186 | 따라서 배열은 선형 자료구조 입니다. 187 | 188 | ### Q) Dynamic Array 에 대해 설명해주세요. 189 | > 💡 자바에서 ArrayList는 List + Array 를 합친 개념입니다. 이 때 배열을 메모리에 연속적으로 저장하면서 크기도 동적으로 변할까? 를 생각 190 | - 현재 배정된 memory를 증가시킬 때, 191 | 1. 확장된 메모리를 확보하고 (New Memory Allocation) 192 | 2. 기존의 Array 값들을 새로운 매모리에 복사해줍니다. (Copy Array to New Memory) 193 | 이를 자동으로 지원해주는 자료구조를 Dynamic Array 라고 합니다. 194 | 195 | ![image](https://user-images.githubusercontent.com/67494004/230757734-1c36e7e3-4ab5-4e84-9be7-b8e25131a74f.png) 196 | 197 | - Size: 현재 값이 배정되어 있는 원소의 크기 198 | - Capacity: 현재 배정된 메모리의 크기. 무조건 Capacity >= Size이어야 함. 199 | - Scaling factor(Growth Factor): 새로운 원소가 들어와서 들어와서 Capacity가 모자라면, Capacity를 늘려야 합니다. 이 때 메모리를 기존 메모리 대비 몇 배나 확장하게 될 지 판단하게 되는데, 이 값을 Scaling Factor라고 합니다. 200 | - 당연하지만, 이 값이 엄청 크면, time 측면에서는 이득이 있으나, 메모리 공간에서는 손해를 봅니다. 201 | 202 | 만약 새로운 값들이 어레이에 계속 들어와서 Capacity와 Size 값이 같아진다면, 기존의 메모리를 유지한 채 새로운 메모리를 추가하는 것이 아니라, 현재 Size * GrowthFactor만큼의 메모리를 확보한 다음, 이 메모리에 기존 값을 모두 복사해줍니다. 203 | 204 | - ArrayList는 데이터 추가 및 삭제 시 메모리를 재할당하기 때문에 속도가 Array보다 느립니다. 205 | 206 | ### 참고 207 | Copy : https://inpa.tistory.com/entry/JAVA-☕-Object-클래스-clone-메서드-얕은-복사-깊은-복사 208 | 자바 정렬 비교 : https://codingnojam.tistory.com/38 209 | https://frhyme.github.io/datastructure/java_dynamic_array/ 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /Data Structure/Graph.md: -------------------------------------------------------------------------------- 1 | # 그래프 2 | ![Untitled-7](https://user-images.githubusercontent.com/67494004/231217994-2ef99b67-83bb-42ec-a0a3-f6d84f728d3b.png) 3 | 4 | 그래프는 노드(N,node)와 그 노드를 연결하는 간선(E,dege)으로 이루어진 자료구조로, 연결되어 있는 객체 간의 관계를 표현할 수 있는 자료구조 입니다. 예를 들어 지도, 지하철 노선도, 도로(교차선, 일방통행길) 등 이 있습니다. 5 | 6 | ### Q) 그래프와 트리의 차이점에 대해 설명해주세요. 7 | - 그래프 8 | - 노드와 노드를 연결하는 간선을 모아놓은 자료구조입니다. 9 | - 루트노드 개념 없음 10 | - 부모-자식 노드 개념이 없음 11 | - 네트워크 구조 12 | - 노드 간 다양한 경로 가능 13 | - 트리 14 | - 트리 또한 그래프이며, 그 중 사이클이 허용되지 않는 그래프를 말합니다. 15 | - 한 개의 루트노드만이 존재 16 | - 부모-자식 관계 있음, 자식노드는 한 개의 부모노드만 가짐. 17 | - 계층적 구조 18 | 19 | ### Q-1) 그래프의 구현 방식에 대해 설명해주세요. 20 | Untitled-8 21 | 22 | 23 | 24 | - 인접 행렬 25 | - 정점의 수 N*N크기의 행렬을 생성해, 행렬의 각 원소를 한 정점이라고 생각하고 인접한 경우에는 1, 인접하지 않은 경우에는 0으로 행렬에 표시합니다. 26 | - 정점 간의 인접 여부를 빠르게 알 수 있다는 장점과, N^2의 메모리 양의 단점이 있습니다. 27 | 28 | 29 | 30 | Untitled-9 31 | 32 | 33 | 34 | - 인접 리스트 35 | - 각각의 **정점에 인접한 정점들을 연결 리스트**로 표시한 것 36 | - 정점과 간선의 삽입이 빠르고 인접 관계를 표시하는 리스트에 사용되는 메모리의 양이 적다는 장점 37 | - 정점 간의 인접 여부를 인접 리스트를 타고 **순차 탐색을 해야한다는 단점** 38 | 39 | 40 | 41 | ### Q-2) 노드가 적고 간선이 많은 경우에는 어떤 구현 방식을 사용하여야 할까요? 42 | - 행렬입니다. 43 | 44 | ### Q) 그래프에 싸이클이 없는 경우는 트리라고 해주셨는데, 그래프에 싸이클이 존재하지 않으면 트리라고 할 수 있을까요? 아니라면 왜 그럴까요? 45 | - 싸이클이 없어도 트리는 계층적 모델이며, 그래프는 연결 형태를 표시하는 것 입니다. 연결 형태만 표시된다면 그래프 라고 할 수 있습니다. 46 | 47 | ![Untitled-6](https://user-images.githubusercontent.com/67494004/231217679-95479814-7458-4911-b456-b94ac83529f1.png) 48 | -------------------------------------------------------------------------------- /Data Structure/Hash.md: -------------------------------------------------------------------------------- 1 | # 해시 2 | 3 | ### 1. 해시란? 4 | - 데이터의 효율적인 관리를 목적으로 임의의 크기를 가진 **데이터(Key)** 를 고정된 크기의 **데이터(Value)** 로 변화시켜 저장하는 것 5 | - Key와 Value를 이용해서 저장하므로, 데이터의 탐색 속도가 **O(1)** 에 수렴한다. 6 | 7 | ### 2. 해시 함수란? 8 | - 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑해주는 함수이다. 9 | 1. **key** : 매핑 전 값 10 | 2. **hash value** : 매핑후 값 11 | 3. **hashing** : 매핑하는 과정 12 | 13 | ### 3. 해시 테이블이란? 14 | ![Image](https://i.imgur.com/NnEBDcX.png) 15 | - key를 hash value로 매핑하고 hash value를 인덱스 삼아서, 저장하고자 하는 value를 저장하는 자료구조이다. 16 | - **Bucket** 은 Hash Table에서 Data가 저장되는 공간이다. 17 | 18 | #### Q) 해시 충돌을 어떻게 해결하는지에 대해서 설명해주세요. 19 | - 해시 충돌은 Hash Value가 겹쳐서 같은 버킷에 저장하려고 할 때 발생합니다. 20 | - 해시 충돌의 해결 방법은 크게 2가지로 구분합니다. 21 | 22 | 23 | **Separate Chaining(분리 연결법)** 24 | ![Image](https://i.imgur.com/7PTT8dT.png) 25 | 26 | - 해시 충돌 시 추가적인 메모리를 사용해 **LinkedList** or **Tree** 를 이용해서 해결하는 방법 27 | - cf) 자바 8 이상에서는 데이터의 사이즈가 커지면 Tree를 이용하고, RB 트리를 이용해 Balanced 트리로 만듦 28 | 29 | **Open Addressing(개방 주소법)** 30 | ![Image](https://i.imgur.com/IM4FA2h.png) 31 | 32 | - chaining과 달리 한 버킷 당 들어갈 수 있는 value가 1개이다. 따라서, 해싱 이후 삽입 시에 이미 도출 된 hash value 버킷에 값이 있다면 다음 주소를 사용하는 방식으로 해결한다. 33 | - **Probing** : 해시 충돌 시 해시 테이블 내의 새로운 주소를 찾는 방법이다. 34 | 1. **Linear Probing(선형 탐사)** 35 | 36 | 37 | - 최초 해시값에 해당하는 버킷에 다른 데이터가 있다면 한칸씩 이동하여 해결한다. 38 | **[문제]** : 특정 해시 값 주변 버킷이 모두 채워져 있는 primary clustering에 취약하다. 39 | 40 | 2. **Quadratic Probing(제곱 탐사)** 41 | 42 | 43 | - 고정 폭으로 이동하는 선형 탐사와 달리 폭이 제곱 수 만큼 늘어나 이동한다. 44 | **[문제]** : 여러 개의 서로 다른 키들이 동일한 초기 해시값을 갖는 secondary clustering에 취약하다. 45 | 46 | - **Double Hashing(이중 해싱)** 47 | - 탐사할 해시 값의 규칙을 제거하는 방식이고 이를 이용해 클러스터링을 방지하기 위한 기법이고, 처음 버킷을 찾을 때의 해시 함수와, Probing을 위한 해시 함수를 별개로 사용한다. 48 | **[문제]** : 3가지 중 캐시 효율이 가장 좋지 않고, 많은 연산량을 요구한다. 49 | - 개방 주소법을 사용한다는 것은 한 버킷 당 한 데이터 밖에 들어가지 못하기 떄문에, load factor가 1과 같거나 작아야 합니다. 50 | #### Q) 왜 Separate Chaining 방식에서 사이즈가 커지면 리스트가 아닌 트리 형식으로 자료를 저장하나요? 51 | - 트리는 **계층적 구조로 구성되어 있는 대용량 데이터를 저장하기 용이한 자료구조**이기 때문에 트리를 사용하는 것이고, Separate Chaining의 트리 방식은 보통 Balanced Tree로 구성되기 떄문에, **이진 탐색을 하는데 기존의 리스트의 탐색 시간인 O(N) 보다 낮은 O(logN) 만큼만 수행**하면 되기 때문에, 트리를 사용합니다. 52 | 53 | #### Q) 해시 테이블의 개념과 동작 원리에 대해서 설명해주세요. 54 | - key를 hash value로 매핑하고 hash value를 인덱스 삼아서, 저장하고자 하는 value를 저장하는 자료구조이다. 55 | - 해시 함수를 통해서 도출된 Hash Value를 이용하여 Hash Value를 인덱스로 가지는 버킷에 데이터를 저장함으로써 탐색할 떄 O(1) 로 수행할 수 있다는 장점이 있습니다. 56 | - **Bucket** 은 Hash Table에서 Data가 저장되는 공간이다. 57 | 58 | #### Q) 해시 테이블의 장단점에 대해서 설명해주세요. 59 | - [장점] : 해시 테이블은 해시 충돌이 발생하지 않았다는 전제하에, 탐색을 O(1) 만에 수행 할 수 있습니다. 60 | - [단점] : 61 | - 해시 충돌이 발생 할 경우 추가적인 연산이 필요하며, Separate Chaning 방식을 사용했을 경우 추가적인 탐색시간이 증가합니다. 62 | - 해시 테이블에 대한 공간도 산정을 해주어야 하는데, 해시 테이블의 공간이 부족할 경우 resize를 해줘야 한다는 단점이 있습니다. 보통 load Factor가 0.75 이상이 되면 2배로 확장합니다. 63 | - 해시 테이블에 대한 정렬을 수행하려면 추가적인 자료구조를 사용해야합니다. 64 | 65 | #### Q) 자바에서의 HashTable과 HashMap의 차이 66 | - HashMap은 key와 value에 null을 허용하지만, HashTable은 null을 허용하지 않습니다. 67 | - **HashMap** 은 데이터의 **동시성 처리를 보장**하지 않지만, **HashTable** 은 **데이터의 동시성 처리를 지원**해서 HashMap에 비해 상대적으로 연산 속도가 느립니다. 68 | - 최근에는 HashTable의 동시성을 개선한 **ConcurrentHashMap**을 사용합니다. 69 | 70 | #### Q) 해시 테이블을 사용했을 때의 탐색, 삽입, 삭제에 대한 시간복잡도 71 | - 삽입, 삭제, 탐색 모두 해시 충돌이 밣생하지 않았을 경우에는 O(1)의 시간복잡도가 발생합니다. 72 | - 해시 충돌 발생 시 해시 충돌을 해결하는 방법에 따라 시간복잡도가 달라질 수 있으며, Separate Chaining 방식을 이용하여 리스트 자료구조를 이용하여 해결했을 경우에는 O(n)까지 중가할 수 있고, 트리 자료구조를 이용하여 해결했을 경우에는 O(logn) 까지 증가할 수 있습니다. 73 | 74 | #### Q) 해시를 사용하는 이유에 대해서 설명해주세요. 75 | - 자원을 관리하는 관점에서 보면 많은 양의 데이터를 적은 양의 데이터를 관리하기 위해서 사용하고, key-value 를 통해서 찾고자 하는 데이터를 빠르게 찾고자 할 때 용이합니다. 76 | 77 | #### Q) 해시 함수를 사용하는 이유와 없을 때의 문제점. 78 | - 해시 함수를 통해서 많은 양의 데이터를 적은 양의 데이터로 관리 할 수 있는데, 해시 함수를 사용하지 않는다면 들어오는 key 별로 데이터를 적재해야하기 때문에 메모리 낭비가 심해진다는 문제가 있습니다. 79 | 80 | #### Q) load-factor에 대해서 설명해주세요. 81 | - 해시 테이블의 버킷에 평균 몇개에 데이터가 저장되는지에 대한 지표입니다. 82 | - N을 키의 개수, M을 해시 테이블의 크기라고 할 때, **N/M** 입니다. 83 | - 따라서, N/M이 1을 초과하게 되면 해시 충돌이 발생합니다. 84 | 85 | #### Q) load-factor가 너무 작거나 크다면 어떤 문제가 있을까요? 86 | - load-factor가 너무 작다면 키의 개수에 비해 **해시 테이블의 크기가 너무 크게 책정되어 메모리가 낭비되고 있다는 것**을 의미합니다. 87 | - load-factor가 너무 크다면 **해시 충돌이 발생을 하게 되는 상황이고, 삽입, 삭제, 탐색 연산에 있어서 추가적인 연산이 발생**한다는 문제가 있습니다. 88 | - 따라서 위와 같은 문제를 해결하기 위해 적절하게 resize를 해줄 필요가 있습니다. 89 | -------------------------------------------------------------------------------- /Data Structure/Readme.md: -------------------------------------------------------------------------------- 1 | ### 자료구조 2 | -------------------------------------------------------------------------------- /Data Structure/Stack, Queue.md: -------------------------------------------------------------------------------- 1 | # Stack, Queue 2 | 스택(Stack)은 top이라 불리는 한쪽 끝에서만 자료를 넣거나 뺄 수 있는 Data Structure입니다. 자료를 넣는 것을 push, 꺼내는 것을 pop이라 하며 가장 마지막에 넣은 자료가 먼저 나오는 Last-In-First-Out(LIFO) 구조입니다. 3 | 큐는(Queue)는 rear라 불리는 한 쪽 끝에서만 자료를 넣고 front라 불리는 반대쪽 한쪽 끝에서만 자료를 뺄 수 있는 Data Structure입니다. 자료를 넣는 것을 자료를 넣는 것을 enqueue, 꺼내는 것을 dequeue이라 하며 가장 먼저 넣은 자료가 먼저 나오는 First-In-First-Out(FIFO) 구조입니다. 4 | 5 | ### Q) 스택과 큐의 내부 구조를 배열로 구현하면 어떻게 구현할 수 있나요? 6 | - stack : JAVA의 ArrayList로 구현을 할 시 push 는 add() 메소드를 통해, pop은 리스트의 맨 앞(인덱스 0)의 요소를 반환하고 제거해줍니다. 7 | - queue : JAVA의 ArrayList로 구현을 할 시 push 는 add() 메소드를 통해, pop은 리스트의 맨 뒤(인덱스 -1)의 요소를 반환하고 제거해줍니다. 8 | ![image](https://user-images.githubusercontent.com/76711238/230778624-da39aed3-e391-4ccd-8e35-b0fec3015bad.png) 9 | 10 | ### Q) 삽입, 삭제가 빈번할텐데, 배열은 정적인 크기를 가지고 있는데 위의 말씀하신 대로라면 배열의 크기가 동적으로 변한다는 문제가 있지 않나요? 11 | JAVA의 ArrayList는 배열과 리스트의 특성을 합친 자료구조입니다. 그렇기에 배열은 정적인 크기를 갖고 있으나, JAVA의 ArrayList는 동적으로 크기를 변하는 것이 가능하기에 괜찮습니다. 12 | 13 | ### Q) 큐의 사용 사례에 대해 설명해주세요. 14 | - 버퍼(Buffer) : 먼저 요청이 들어온 요청부터 먼저 처리해줍니다. 15 | (+) 버퍼 사용 이유 16 | 버퍼를 사용하지않으면 입력과 즉시 데이터가 전송되기때문에 전송타겟에 부하가 걸릴 수 있습니다. 17 | 입력된것을 한번에 묶어서 전달하기에 전송시간이 줄어들며, 성능이 향상합니다. 18 | 더 나아가, 사용자가 잘못 입력시 수정도 가능하다는 장점을 갖고 있습니다. 19 | 그러나 입력과 즉시 데이터 전송을 하지않기 때문에 반응시간이 느립니다. 20 | 21 | ### Q) 스택의 사용 사례에 대해 설명해주세요. 22 | - call stack : 함수의 순서를 저장해두는 데 사용됩니다. 23 | - 웹 브라우저 뒤로가기 : 가장 나중에 열린 페이지부터 뒤로 가기를 실행합니다. 24 | - 문서작업에서 Ctrl+Z : 가장 나중에 수정한 내역부터 되돌립니다. 25 | 26 | ### Q) 스택으로 큐를 구현하는 방법에 대해 설명해주세요. 27 | 💡 스택 한개는 InBox, 한 개는 OutBox 용도로 만듭니다. 28 | 1. inBox에 데이터를 push(삽입)합니다. ex) 4→ 3→ 2→ 1 29 | ![image](https://user-images.githubusercontent.com/76711238/230779672-472b90f2-1c42-4528-b282-459f49fdc2e4.png) 30 | 2. inBox에 있는 데이터를 pop(추출) 하여 outBox에 push(삽입)합니다. ex) 1→ 2→ 3→ 4 31 | ![image](https://user-images.githubusercontent.com/76711238/230779686-f5e1b205-60bf-4221-b2e8-d5a19ac94919.png) 32 | ![image](https://user-images.githubusercontent.com/76711238/230779691-e21859b5-e243-4218-b222-86b0ef9a486b.png) 33 | 3. outBox에 있는 데이터를 pop(추출) 합니다. - 4→ 3→ 2→ 1 34 | ![image](https://user-images.githubusercontent.com/76711238/230779703-6be2f97e-df2c-4539-b74d-6fc639d1612a.png) 35 | 36 | ### Q) 큐로 스택을 구현하는 방법에 대해 설명해주세요. 37 | 💡 큐 한 개는 메인 큐, 다른 큐는 임시 큐 용도로 둡니다. 38 | 1. 메인 큐에 값을 넣습니다.(put) ex) 1→ 2→ 3 → 4 39 | ![image](https://user-images.githubusercontent.com/76711238/230779529-c38d703f-7c57-40b0-be27-e8f3bd0ca381.png) 40 | 2. 메인 큐에 1개의 원소가 남을 때까지 get 한 값을 임시 큐에 put 합니다. 41 | ![image](https://user-images.githubusercontent.com/76711238/230779545-fb44dd74-e49c-47c1-a0b6-fb4359b571ae.png) 42 | 3. 마지막 남은 원소는 result 변수에 저장합니다. 43 | ![image](https://user-images.githubusercontent.com/76711238/230779569-9be41f2e-c13f-45a9-8dbc-760bf815ea83.png) 44 | 4. 임시 큐에 있는 원소들을 메인 큐로 모두 이동시킵니다. (get → put) 45 | ![image](https://user-images.githubusercontent.com/76711238/230779584-f67516c4-3bea-4feb-92e9-50d5df42b0e1.png) 46 | 5. result 값을 리턴합니다. 47 | 48 | ### Q) Stackoverflow 현상에 대해 설명해주세요. 49 | - Stack overflow는 스택 포인터가 메모리 내 스택의 경계를 넘어갈 때 발생하는 에러입니다. 해당 변수의 크기가 Stack보다 크거나, 함수를 무한으로 호출하고 있을 때, 혹은 Stack을 넘어가 다른 곳에 위치하고 있는 경우에 주로 발생합니다. 50 | - (+) Stack은 높은 주소 (High Address)부터 낮은 주소 (Low address)로 메모리에 할당됩니다. 51 | ![image](https://user-images.githubusercontent.com/76711238/230779310-e1e1b9dd-05df-4a26-8782-0f650d3765c6.png) 52 | 53 | ### Q-1) 해결하는 방법은 무엇이 있나요? 54 | - JAVA VM 옵션에서 스택의 크기를 증가시켜주면 됩니다. 55 | 56 | ### Q) Messaging queue에 대해 아는 데까지 말씀해주세요. 57 | - 메시지 큐는 메시지를 임시로 저장하는 간단한 버퍼라고 생각하면 됩니다. 메시지를 전송 및 수신하기 위해 중간에 메시지 큐를 두는 것입니다. 58 | - 메시지 전송 시 생산자(Producer)로 취급되는 컴포넌트가 메시지를 메시지 큐에 추가합니다. 해당 메시지는 소비자(Consumer)로 취급되는 또 다른 컴포넌트가 메시지를 검색하고 이를 사용해 어떤 작업을 수행할 때까지 메시지 큐에 저장됩니다. 59 | ![image](https://user-images.githubusercontent.com/76711238/230777739-cd082bdc-ac8b-4477-bef3-aab5e2a0a59f.png) 60 | - 사용하는 이유 : 메시지 큐는 소비자(Consumer)가 실제로 메시지를 어느 시점에 가져가서 처리하는 지는 보장하지 않습니다. 언젠가는 큐에 넣어둔 메시지가 소비되어 처리될 것이라고 믿습니다. 61 | 이러한 비동기적 특성 때문에 메시지 큐는 실패하면 치명적인 핵심 작업보다는 **어플리케이션의 부가적인 기능**에 사용하는 것이 적합합니다. 62 | - 메시지 큐의 이점 63 | - 비동기(Asynchronous) 64 | 메시지 큐는 생산된 메시지의 저장, 전송에 대해 동기화 처리를 진행하지 않고, 큐에 넣어 두기 때문에 나중에 처리할 수 있습니다. 여기서, 기존 동기화 방식은 많은 메시지(데이터)가 전송될 경우 병목이 생길 수 있고, 뒤에 들어오는 요청에 대한 응답이 지연됩니다. 65 | - 낮은 결합도(Decoupling) 66 | 생산자 서비스와 소비자 서비스가 독립적으로 행동하게 됨으로써 서비스 간 결합도가 낮아집니다. 67 | - 확장성(Scalable) 68 | 생산자 서비스 혹은 소비자 서비스를 원하는 대로 확장할 수 있기 때문에 확장성이 좋습니다. 69 | - 탄력성(Resilience) 70 | 소비자 서비스가 다운되더라도 어플리케이션이 중단되는 것은 아닙니다. 메시지는 메시지 큐에 남아 있습니다. 소비자 서비스가 다시 시작될 때마다 추가 설정이나 작업을 수행하지 않고도 메시지 처리를 시작할 수 있습니다. 71 | - 보장성(Guarantees) 72 | 메시지 큐는 큐에 보관되는 모든 메시지가 결국 소비자 서비스에게 전달된다는 일반적인 보장을 제공합니다. 73 | 74 | ### Q) 우선순위 큐는 어떤 자료구조로 구현돼있나요? 75 | heap을 통해서 구현합니다. 76 | ### Q-1) 왜 heap을 사용하나요? 77 | heap은 최대, 최소값을 반환하는데 특화된 (시간복잡도 O(1)) 자료구조입니다. 우선순위가 높은/낮은 데이터 추출에 가장 빠르게 반환할 수 있는 자료구조이기 때문입니다. 78 | 79 | ### Q-2) heap을 toString()으로 출력한다면 순서대로 나올까요? 80 | 아닙니다. heap은 tree로 구성된 자료구조이기에, 순서대로가 아닌 트리 노드에 담긴 순서대로 나올 것 입니다. 81 | 82 | ### Q-3) 우선순위 큐의 사용사례는 무엇이 있나요? 83 | 우선순위가 가장 높은 것을 추출할 때 사용됩니다. 84 | 1. 다익스트라 알고리즘(Dijkstra’s algorithm) : 최소 값을 찾을 때 우선순위 큐가 사용됩니다. 85 | 2. 힙정렬: 많은 힙 정렬에서는 우선순위 큐를 사용합니다. 86 | 3. 허프만 코딩: 문자열을 트리를 이용해 2진수로 압축하는 알고리즘이고 min-Priority를 사용합니다. 87 | 88 | ### Q) 양방향 큐는 무엇인가요? 89 | - 덱(Deque)는 양방향에서 요소를 추가하고 제거할 수 있는 양방향 큐입니다. 90 | 큐는 맨 뒤 요소 (rear) 에 값을 추가하고, 맨 앞 요소 (front) 의 값을 삭제하는 방식이지만 덱(Deque)는 맨 앞에 추가할수고, 맨 뒤를 삭제할 수도 있습니다. 91 | - 스택처럼 사용할 수도 있고 큐 처럼 사용할 수도 있는 자료구조입니다. 92 | - 단방향 큐를 일반적인 리스트(list) 로 구현할 때 요소를 추가하고 제거할 때의 복잡도는 O(n) 인 반면, 양방향에서 값을 추가하고 제거하는 처리의 복잡도는 O(1)로 구현할 수 있습니다. 93 | ![image](https://user-images.githubusercontent.com/76711238/230778945-11fba7c9-b633-4cad-b10e-27e234e65729.png) 94 | 95 | #### 사진 & 내용 출처 96 | https://tecoble.techcourse.co.kr/post/2021-09-19-message-queue/ 97 | https://pro-programmer.tistory.com/4 98 | https://cocoon1787.tistory.com/691 99 | https://80000coding.oopy.io/bab54a8f-01de-4dcc-9630-2e8eaae9ed67 100 | https://underdog11.tistory.com/entry/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Priority-Queues-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%ED%81%90 101 | https://ryu-e.tistory.com/96 102 | -------------------------------------------------------------------------------- /Data Structure/Tree & Heap.md: -------------------------------------------------------------------------------- 1 | # 트리 2 | 3 | ### Q) 트리 중 이진트리에 대해 설명해주세요. 4 | 5 | - 트리는 노드로 이루어진 자료구조로 스택이나 큐와 같은 선형 구조가 아닌 비선형 자료구조입니다. 6 | - 다음과 같은 특징이 있습니다. 7 | 8 | - 1. 트리는 하나의 루트 노드를 갖는다. 9 | 10 | - 2. 루트 노드는 0개 이상의 자식 노드를 갖는다. 11 | 12 | - 3. 자식 노드 또한 0개 이상의 자식 노드를 갖는다. 13 | 14 | - 4. 노드(Node)들과 노드들을 연결하는 간선(Edge)들로 구성되어 있다. 15 | 16 | - 트리에는 사이클(cycle)이 존재할 수 없다. 여기서 사이클이란 시작 노드에서 출발해 다른 노드를 거쳐 다시 시작 노드로 돌아올 수 있다면 사이클이 존재한다고 한다. 17 | syn_async 18 | 19 | - 트리는 사이클(cycle)이 없는 하나의 연결 그래프(Connected Graph)라고 할 수 있다. 20 | 트리의 노드는 self-loop가 존재 해서는 안된다. 21 | syn_async 22 | 23 | syn_async 24 | 25 | **루트 노드(root node)** : 부모가 없는 노드로 트리는 단 하나의 루트 노드를 가진다. (ex : A- 루트노드) 26 | 27 | **단말 노드(leaf node)** : 자식이 없는 노드로 terminal 노드라고도 부른다. (ex : C, D, E - 단말 노드) 28 | 29 | **내부 노드(internal node)** : 단말 노드가 아닌 노드(ex : A, B - 내부 노드) 30 | 31 | **간선(edge)** : 노드를 연결하는 선 32 | 33 | **형제(sibling)** : 같은 부모 노드를 갖는 노드들 (ex : D-E, B-C : 형제) 34 | 35 | **노드의 깊이(depth)** : 루트 노드에서 어떤 노드에 도달하기 위해 거쳐야 하는 간선의 수(ex : D의 depth : 2) 36 | 37 | **노드의 레벨(level)** : 트리의 특정 깊이를 가지는 노드의 집합 ( ex : level 1- {B, C} ) 38 | 39 | **노드의 차수(degree)** : 자식 노드의 개수 ( ex : B의 degree - 2, C의 degree - 0) 40 | 41 | **트리의 차수(degree of tree)** : 트리의 최대 차수 ( ex : 위 트리의 차수는 2이다) 42 | 43 | ### Q-1) 이진트리 검색과 삭제 시간 복잡도 평균에 대해 설명해주세요. 44 | 45 | - 이진 트리의 검색과 삭제 시간 복잡도는 트리의 높이에 의해 결정됩니다. 따라서 이진 트리의 높이가 h라면, 검색과 삭제는 O(h) 시간이 걸립니다. 46 | 47 | 이진 탐색 트리의 경우, 평균 높이는 O(log n)이므로 검색과 삭제의 평균 시간 복잡도는 `O(log n)`입니다. 이진 탐색 트리의 높이가 O(log n)이 되는 것은 키 값들이 무작위로 배치될 때 발생하며, 이 경우 대부분의 검색과 삭제 작업은 O(log n) 시간 안에 수행됩니다. 48 | 49 | 하지만 이진 탐색 트리에서 키 값들이 일정한 패턴으로 배치되는 경우, 트리의 높이가 n-1이 될 수 있습니다. 이러한 경우, 검색 및 삭제 연산의 시간 복잡도는 O(n)이 됩니다. 50 | 51 | 따라서, 이진 탐색 트리의 검색 및 삭제 연산의 평균 시간 복잡도는 O(log n)이며, `최악의 경우 O(n)`이 될 수 있습니다. 52 | 53 | ### Q-2) 편형된 트리를 보완할 수 있는게 있을까요? 54 | 55 | - Balanced Tree(균형 트리)가 있습니다. 균형 트리는 트리의 높이가 가능한 작은 상태를 유지하는 이진 탐색 트리의 일종입니다. 이진 탐색 트리에서 키 값들이 무작위로 배치되지 않은 경우, 트리의 높이는 O(n)이 될 수 있습니다. 이 경우, 검색 및 삭제 작업의 시간 복잡도가 O(n)이 되므로 효율적인 이진 탐색 트리가 아닙니다. 56 | 57 | 반면에 균형 트리는 트리의 높이를 가능한 작게 유지하기 위해 노드의 삽입, 삭제 등의 작업을 수행할 때 트리의 구조를 조정합니다. 대표적인 균형 트리로는 AVL 트리, 레드-블랙 트리, B-트리 등이 있습니다. 58 | 59 | ### Q) AVL 트리와 레드블랙트리에 대해 알고계신가요? 60 | 61 | - 이진탐색트리의 문제점을 극복할 수 있는 자료구조이다. 이진탐색트리에서 한쪽으로 노드가 쏠리게되면 최악의 경우 O(N)의 시간이 필요하기때문에 성능이 저하된다. 62 | 63 | - AVL트리는 다음과 같은 특징을 가진다. 64 | 65 | - 이진 탐색 트리의 속성을 가진다. 66 | - 왼쪽, 오른쪽 서브 트리의 높이 차이가 최대 1이다. 67 | - 높이 차이가 1보다 커지면 회전(Rotation)을 통해 균형을 맞춰 높이 차이를 줄인다. 68 | - 삽입, 검색, 삭제의 시간 복잡도가 O(log N)이다. (N : 노드의 개수) 69 | 70 | - Balance Factor(BF) 71 | - 왼쪽과 오른쪽의 자식의 높이 차이를 뜻합니다. 72 | - 회전 73 | - 불균형한 트리로 바로잡기 위해서는 회전이 필요합니다. 74 | 75 | ### Q-1) AVL과 레드블랙 차이에 대해 알려주세요. 76 | 77 | 1. AVL트리는 더욱 엄격한 균형을 이루고 있기 때문에 `Red-Black 트리보다 더 빠른 조회를 제공` 78 | 79 | 2. Red-Black 트리는 상대적으로 느슨한 균형으로 인해 회전이 거의 이루어지지 않기 때문에 AVL트리보다 빠르게 삽입 및 제거 작업을 수행 80 | 81 | 3. AVL트리는 각 노드에 대해 BF를 저장하므로 노드 당 int 저장이 필요 82 | 83 | 4. Red-Black 트리는 노드당 1비트의 정보만 필요합니다. (플래그 반전만 시키면 됨) 84 | 85 | 5. Red-Black 트리는 맵, C++의 멀티캐스트, Java treeMap 등 대부분의 언어 라이브러리에서 사용, AVL트리는 더 빠른 검색이 필요한 데이터베이스에서 사용 86 | 87 | ### Q) Balanced 트리의 시간 복잡도 최악이 어떻게 될까요? 88 | 89 | - 균형 트리의 검색, 삽입, 삭제 연산의 최악 시간 복잡도는 `O(log n)`입니다. 이는 이진 탐색 트리의 경우와 동일하며, 트리가 균형을 유지하므로 트리의 크기 n에 대해 항상 일정한 시간 복잡도를 보장합니다. 90 | 91 | ### Q) 이진트리와 이진 탐색 트리를 각각 비교해서 설명해주세요. 92 | 93 | - 이진 트리는 각 노드가 최대 2개의 자식 노드를 가지는 트리로, 왼쪽 자식 노드는 부모 노드보다 작은 값, 오른쪽 자식 노드는 부모 노드보다 큰 값이 저장됩니다. 94 | 95 | - 이진 탐색 트리는 이진 트리의 일종으로, 각 노드의 왼쪽 자식 노드는 부모 노드보다 작은 값, 오른쪽 자식 노드는 부모 노드보다 큰 값이 저장되는 트리입니다. 이진 탐색 트리는 검색이나 정렬에 용이합니다. 96 | 97 | ### Q) 3가지 순회방식에 대해서 알고 계신가요? 98 | 99 | - syn_async 100 | 101 | 전위 순회 : 0->1->3->7->8->4->9->10->2->5->11->6 102 | 103 | 중위 순회 : 7->3->8->1->9->4->10->0->11->5->2->6 104 | 105 | 후위 순회 : 7->8->3->9->10->4->1->11->5->6->2->0 106 | 107 | ### Q) 정렬이 된 상태에서 출력한 값을 보고 싶다면 어떤 순회를 사용해야할까?? 108 | 109 | - 중위 순회는 왼쪽 서브트리, 현재 노드, 오른쪽 서브트리 순서로 노드를 탐색하는 방법입니다. 이진 탐색 트리의 특성 상 중위 순회를 사용하면 노드가 정렬된 순서대로 출력됩니다. 즉, 중위 순회를 수행하면 정렬된 값을 순서대로 출력할 수 있습니다. 110 | 111 | 중위 순회의 시간 복잡도는 트리의 크기에 비례합니다. 따라서 이진 탐색 트리가 균형을 유지하는 경우, 중위 순회의 시간 복잡도는 O(n log n)입니다. 하지만, 트리의 높이가 매우 높은 경우, 중위 순회의 시간 복잡도는 O(n)이 될 수 있습니다. 112 | 113 | ### Q) 후위순회를 사용하는 사례에 대해 설명해주세요. 114 | 115 | - 후위 순회는 이진 트리의 각 노드에 대한 작업을 수행하기에 적합합니다. 예를 들어, 후위 순회를 사용하여 이진 트리에서 수식을 계산하거나, 트리에서 각 노드의 깊이를 계산하는 등의 작업을 수행할 수 있습니다. 116 | 117 | 또한, 후위 순회는 이진 트리에서 메모리 해제 등의 정리 작업을 수행할 때에도 유용합니다. 이는 노드의 자식 노드들을 모두 방문한 후, 부모 노드를 방문하며 메모리를 해제하기 때문입니다. 118 | 119 | ### Q) 해시테이블말고 이진 탐색 트리를 사용하는 이유와 각 차이에 대해 설명해주세요. 120 | 121 | - 기능적인 측면에서 보면 탐색, 삭제, 삽입과 같은 기본기능들에 대해서, `해시 테이블` : O(1) 122 | `이진탐색트리` : O(logN) 정도 성능으로 동작한다. 123 | 124 | 해시 테이블의 해시 함수의 비용과, 충돌 해결비용까지 고려하더라도 `데이터가 엄청 많아지는` 경우에는 해시 테이블이 효과적이라고 볼 수 있다. 그리고 만약 입력 사이즈를 알고 있다면, 입력 사이즈에 맞게 최적화된 해시 함수를 이용하여 해시 테이블의 해시 값을 균일하게 분포시켜서 성능을 최적화시킬 수 있을 것이다. 125 | 126 | 127 | 128 | 하지만 이진탐색트리에는 `데이터들의 순서가 정렬`된 상태로 유지된다는 강력한 장점이 있다. 이 특성으로 인해 데이터를 정렬된 형태로 순회할 수 있다는 장점도 있겠지만, 아주 좋은 성능으로 범위기반 쿼리가 가능하다는 장점도 있다. 그러므로 `순서와 밀접한 연관이 있는 데이터` 를 다루는 상황에서는 이진탐색트리가 효과적일 것이다. 또한 문자열과 같은 데이터를 다루는 상황에서는 키의 동등 비교를 수행하는 해시 테이블보다, 키의 크기 비교를 수행하는 이진트리가 유리할 것이다. 129 | 130 | - 메모리 측면에서보면 이진탐색트리는 딱 필요한 원소 만큼의 공간만을 할당하는 반면, 해시 테이블은 해시 적중률을 높이기 위해 `원소의 개수 이상의 메모리`를 유지해야한다. 그러므로 사용량 측면에서는 이진탐색트리가 유리하다. 131 | 132 | - 캐시 적중률 측면에서 보면 이진탐색트리는 노드 기반 자료구조로 메모리 파편화가 진행되어 `캐시 적중률`이 떨어지게 된다. 반면, 해시 테이블은 배열 기반 자료구조로 연속된 메모리를 유지하기 때문에 `캐시 적중률이 상당히 높다`. 133 | 134 | ### Q) b-tree / b+tree 차이에 대해 설명해주세요. 135 | 136 | - ![image](https://user-images.githubusercontent.com/43171179/231002733-cdbe6c03-a171-4080-a0e5-e5ae629a13b4.png) 137 | 138 | B-Tree 는 위 그림과 같이 생겼습니다. Binary-Tree 라고 오해를 하지만 Balanced-Tree 를 의미합니다. 자식이 2개 이상 가능합니다. 139 | 140 | B-tree 는 균형 트리로 루트로부터 리프까지의 거리가 일정한 트리 구조입니다. 이렇게 균형을 유지할 경우 어떤 데이터를 검색할 때 빠른 속도로 데이터를 찾을 수 있습니다. 하지만 만약 트리의 노드가 수정되어야 한다면 재정렬을 해줘야 하기 때문에 수정시 약점이 있습니다. 141 | 142 | MySQL의 InnoDB에서 사용되는 B+Tree 는 리프 노드를 제외하고 값을 담아두지 않기 때문에 하나의 블록에 더많은 Key 들을 담아 둘 수 있다 는 장점이 있습니다. 이는 곧, 트리의 높이가 낮아짐을 나타냅니다. 143 | 144 | 풀 스캔시 B+Tree는 `리프 노드에 데이터`가 모두 있기 때문에 한번의 선형 탐색만 하면 되기 때문에 B-Tree 에 비해 빠르다 는 장점이 있습니다. 참고로 같은 레벨의 노드에서는 `Double Linked List` 를 사용하고 자식 노드는 `Single Linked List` 를 사용합니다. 145 | 146 | ### Q-1) 노드가 이진트리는 2개였는데 b-tree도 2개만 가지고 있나요? 147 | 148 | - B-트리(B-tree)는 이진 트리와 달리 자식 노드의 개수가 정해져 있지 않습니다. 각 노드는 여러 개의 자식 노드를 가질 수 있습니다. 149 | 150 | ### Q) 완전 이진 트리랑 불안전 이진 트리는 어떻게 구분? 151 | 152 | - 완전 이진 트리(Complete Binary Tree)는 모든 레벨에서 노드가 꽉 차 있고, 마지막 레벨에서는 오른쪽부터 순서대로 노드가 채워진 이진 트리를 말합니다. 이와 반대로, 불완전 이진 트리(Incomplete Binary Tree)는 모든 레벨에서 노드가 꽉 차 있지 않거나, 마지막 레벨에서 오른쪽에서부터 노드가 채워져 있지 않은 이진 트리를 말합니다. 153 | 154 | ### Q) 힙과 이진 탐색 트리의 차이점? 155 | 156 | - 구현 방식 157 | 158 | `이진 탐색 트리`: 모든 노드의 왼쪽 서브트리에는 해당 노드보다 작은 값의 노드들이, 오른쪽 서브트리에는 해당 노드보다 큰 값의 노드들이 위치합니다. 각 노드의 값은 자신을 기준으로 왼쪽 서브트리에는 작은 값의 노드들만, 오른쪽 서브트리에는 큰 값의 노드들만 저장됩니다. 삽입/삭제 연산 시 최악의 경우 O(h)의 시간 복잡도를 가집니다. 이 때 h는 트리의 높이를 의미합니다. 만약 트리가 한쪽으로 치우쳐져 있을 경우, 삽입/삭제 연산 시간이 O(n)으로 급증할 수 있습니다. 159 | 160 | `힙`: `완전 이진 트리 형태`를 띄며, 부모 노드와 자식 노드 간의 대소 관계가 정해져 있습니다. 161 | 노드 값의 저장 방식입니다. 부모 노드와 자식 노드 간의 대소 관계가 정해져 있어, 최대 힙(Max Heap)의 경우 부모 노드의 값이 자식 노드의 값보다 크고, 최소 힙(Min Heap)의 경우 부모 노드의 값이 자식 노드의 값보다 작습니다. 삽입/삭제 연산 시 `최악의 경우 O(log n)의 시간 복잡도`를 가집니다. 트리의 높이가 균형적으로 유지되기 때문에 이진 탐색 트리와 달리 삽입/삭제 연산 시간이 일정합니다. 162 | 163 | 따라서 이진 탐색 트리는 `탐색 연산에 더 유리`하며, `삽입/삭제 연산이 빈번하지 않은 경우에 적합`합니다. 반면에 힙은 `최대/최소값을 빠르게 찾을 수 있으며`, `삽입/삭제 연산이 빈번한 경우에 적합`합니다. 164 | 165 | ### Q) 힙에도 작은 값은 왼쪽, 큰 값은 오른쪽으로 가는 성질이 적용될까요? 166 | 167 | - 힙은 이진 탐색 트리와 달리 부모 노드와 자식 노드 간의 대소 관계가 정해져 있으며, 부모 노드의 값이 자식 노드의 값보다 큰 경우를 최대 힙(Max Heap)이라고 합니다. 최소 힙(Min Heap)의 경우는 부모 노드의 값이 자식 노드의 값보다 작은 경우입니다. 168 | 169 | ### Q) 이진 탐색트리랑 힙에서 중복된 값을 삽입하는게 가능할까요? (힙은 중복가능) 170 | 171 | - 이진 탐색 트리는 중복을 허용하지 않고, 힙은 중복을 허용한다. 172 | 173 | ### Q) 힙 삽입 삭제 시 연산이 어떻게 일어날까요? 174 | 175 | - 삭제할 값을 선택합니다. 최대 힙(Max Heap)의 경우 루트 노드에 있는 가장 큰 값을 선택하고, 최소 힙(Min Heap)의 경우 루트 노드에 있는 가장 작은 값을 선택합니다. 176 | 177 | 삭제할 값을 힙의 맨 마지막 노드와 교환합니다. 178 | 179 | 힙의 맨 마지막 노드를 삭제합니다. 180 | 181 | 변경된 노드를 힙의 구조에 맞게 재정렬합니다. 최대 힙(Max Heap)의 경우, 루트 노드로부터 아래로 내려가며 자식 노드 중 가장 큰 값을 가진 노드와 교환해 나가며 정렬합니다. 최소 힙(Min Heap)의 경우도 마찬가지로, 루트 노드로부터 아래로 내려가며 자식 노드 중 가장 작은 값을 가진 노드와 교환해 나가며 정렬합니다. 182 | -------------------------------------------------------------------------------- /Database/Clustering, Replication.md: -------------------------------------------------------------------------------- 1 | # 클러스터링 2 | - 동일한 데이터베이스를 여러 대의 서버가 관리하도록 클러스터를 구축하는 것. 3 | - 클러스터링을 이용함으로써 하나의 서버에 몰리던 부하를 여러 곳으로 분산 시키는 로드 밸런싱이 가능해집니다. 4 | 5 | #### 클러스터링의 종류 6 | 1. **Active-Active 방식** 7 | - Active-Active 방식은 동일한 데이터 베이스를 여러 대의 서버가 관리하도록 하는 상태에서, 관리하는 서버들을 모두 켜놓는 상태를 말합니다. 8 | **[장점]** : 하나의 데이터베이스 서버가 죽더라도 바로 다른 데이터베이스에서 필요한 작업을 수행하면 되기 때문에 클라이언트 입장에서는 서버의 문제가 없는 것처럼 받아들일 수 있고, 안정적인 서비스를 운영 할 수 있습니다. 9 | **[단점]** : 여러 대의 서버가 데이터베이스를 공유하므로 병목현상이 발생해서 더 많은 비용이 발생할 수 있고, 여러 개의 서버를 지속적으로 운영하는 과정에서 서버 비용이 많이 소모될 수 있습니다. 10 | 2. **Active-StandBy 방식** 11 | - Active-Active 방식과 달리 모든 서버를 열어두는 것이 아니고, 주 서버를 Active 상태로 유지를 하다가 Active 상태에 문제가 생기면 StandBy 즉, 실행중이지 않고 대기중이었던 데이터베이스 서버를 Active 상태로 전환해서 사용하는 방식입니다. 이러한 방식을 **FailOver** 방식이라고 합니다. 12 | **[장점]** : 기존의 Active-Active 방식에 비해서 상대적으로 비용이 덜 들게 되고 병목현상도 덜 발생하게 됩니다. 13 | **[단점]** : Acitve 서버가 문제가 발생했을 경우 StandBy 서버를 Active 서버로 전환하는데에 시간이 소요되어 그 기간동안 클라이언트들은 서비스를 이용할 수 없다는 문제가 있고, Active-Active 방식에 비해서 로드 밸런싱 효율도 떨어진다는 문제가 있습니다. 14 | 15 | ### Q) 레디스 클러스터링 방식 16 | - Redis Cluster 방식은 데이터를 자동으로 여러 개의 Redis 노드에 나누어 저장할 수 있는 방법을 제공합니다. 이때, 일부 노드가 죽거나 통신이 되지 않을 때에도 작업을 계속 할 수 있는 가용성을 제공합니다. 17 | - 단, 과반수의 master 노드가 죽는 경우에는 클러스터도 중단됩니다. 18 | - Redis 6.0 부터 ThreadedIO가 추가되어 사용자 명령에 대해서는 멀티 쓰레드가 지원되지만, 명령어를 실행하는 코어 부분은 싱글 쓰레드로 동작합니다. 19 | 20 | # 리플리케이션 21 | - 리플리케이션은 복제된 데이터베이스를 운용하는 방식입니다. 22 | - 이때, 원본 데이터베이스를 Master, 복제된 데이터베이스를 Slave라고 부릅니다. Slave 데이터베이스는 Master 데이터베이스를 복제하여 동일한 데이터를 가지게 됩니다. 23 | 24 | **[장점]** 25 | 1. 리플리케이션은 Master 데이터베이스와 Slave 데이터베이스에 각기 다른 명령을 수행하도록 할 수 있습니다. 이로 인해, Insert, Update, Delete 등의 무거운 작업은 Master에 일임하고, Select 같이 가벼운 작업은 Slave에 일임해 부하를 분산시킬 수 있습니다. 26 | 2. 리플리케이션을 이용하면 데이터 안정성을 획득할 수 있고, Master 데이터베이스의 데이터가 손상되었을 때 Slave 데이터베이스에 복제된 데이터를 통하여 복구할 수 있습니다. 27 | 28 | **[단점]** 29 | 1. Slave에 Master의 데이터를 복제할 때 비동기로 동기화가 됩니다. 이에 따라 데이터의 일관성이 깨질 수 있는 상황이 생길 수도 있습니다. 이때, 복제를 하기 위해 Binary Log 를 사용합니다. 30 | 31 | ### Q) 무거운 연산과 가벼운 연산이 무엇인지에 대해서 설명해주세요. 32 | - 무거운 연산은 주로 CREATE, DELETE, UPDATE 등을 의미하고, 가벼운 연산은 SELECT를 의미합니다. 33 | 34 | ### Q) MYSQL 데이터베이스 리플리케이션 실행 방식에 대해서 설명해주세요. 35 | 1. **Async Replication** 36 | - MySQL이 기본적으로 채택하는 Replication 방식이고, Binary Log을 사용하여 복제를 합니다. Binary Log에는 MySQL의 모든 변경 사항이 기록이 되고, Slave DB가 이 Binary Log를 이용하여 Replication을 수행하는 방식입니다. 37 | - 하지만, replicaiton이 async 방식으로 동작해서 Master 에서는 Slave의 복제 여부등을 확인하지 않아 데이터 일관성 문제를 발생할 수가 있고, Slave의 부하 정도, 시스템 사용륭, 네트워크 속도 등 여러가지 이유로 Replication이 지연될 수 있습니다. 38 | 39 | 2. **Semi-Sync Replication** 40 | - MySQL 5.5 버전에서 도입된 방식입니다. Master DB에서 Slave로 전달된 Relay log의 기록이 완료되었다는 메시지를 받고나서 처리중인 트랜잭션의 결과를 클라이언트에게 반환합니다. 41 | - Async 방식에 비하면 성능이 저하되지만 완전한 sync 방식 보다는 성능 저하가 덜하고, 변경이 전달된 이후에 클라이언트에게 결과를 반환하기 때문에, 데이터 동기화를 더욱 보장해 줄 수 있습니다. 42 | 43 | 3. **binlog** 44 | - Binary log는 DDL 과 DML 같이 데이터베이스 내에서 발생하는 변경 내역들이 저장되는 로그 파일 입니다. 45 | - 이러한 로그 파일은 **row, mixed, statement** 3가지 포맷을 가지고 있습니다. 46 | 1. **statement** : 전통적으로 사용하던 방식으로 실행된 쿼리 구문 그대로 Binlog에 남겨지는 방식 47 | 2. **row** : 생성/변경된 데이터의 Before/After row image가 binlog에 저장하여, 사이즈가 statement보다 크게 생성 48 | 3. **mixed** : row와 statement 중간 형태로 날짜와 같이 determine이 필요한 경우 row형태로 저장되는 형식 49 | 50 | ### Q) 클러스터링과 리플리케이션의 차이점에 대해서 설명해주세요. 51 | - 클러스터링은 동일한 데이터베이스를 각 다른 서버에서 관리하는 방식이고, 리플리케이션은 동일한 데이터베이스를 하나의 서버에서 데이터베이스를 복제해서 사용하는 방식으로 사용합니다. 52 | ### Q-1) 동기, 비동기 관점에서도 설명해주세요. 53 | - 이때, 클러스터링은 같은 데이터베이스를 단순히 각기 다른 서버에서 관리를 하다보니, 동기로 동작하고 리플리케이션은 동일한 서버에서 데이터베이스를 복제해서 사용하므로, Master 데이터베이스를 Slave 데이터베이스에 데이터를 복제하는 과정이 필요해서 비동기로 동작합니다. 54 | 55 | ### Q-2) 클러스터링과 리플리케이션은 각각 어느 상황에서 사용하는 것이 좋을까?. 56 | - 클러스터링은 리플리케이션에 비해서 가용성 측면에서 많은 장점을 가져다주고 추가적으로 부하 분산을 위한 로드밸런싱도 리플리케이션에 비해서 좋기 때문에 안정적인 서비스를 하기 위한 목적이라면 클러스터링을 사용합니다. 57 | - 리플리케이션은 서버는 안정적이지만 무거운 쿼리에 대한 응답 속도를 높이고 이에 따라 부하를 분산 시켜 성능 최적화를 하고 싶을 때 사용하는 것이 좋습니다. 58 | 59 | ### Q) 분산 락을 어떻게 구현 할 것 같은지 답변을 해주세요. 60 | - 제 3의 서버로 레디스를 두고 분산 데이터베이스에 락에 대해서 락을 레디스에서 잠궈두고 구독자-발행자 패턴을 사용하여 락이 풀리게 되면 그때 제일 처음 진입한 구독자에 대해서 락 권한을 주어 접근 할 수 있도록 합니다. 61 | - 혹은 낙관적 락을 택하고, 트랜잭션을 수행하면서 데이터의 불일치성이 발견되면 그 떄, 애플리케이션 단계에서 연쇄 롤백을 처리하는 방법도 있습니다. 하지만 이는 구현하기가 복잡하고, 클라이언트에게 안 좋은 서비스 경험도 줄 수 있습니다. 62 | 63 | ### Q) GTID가 무엇인지 설명해주세요. 64 | - GTID는 Global Transaction IDentifier의 약자로 MySQL 데이터베이스에서 커밋되는 각 트랜잭션과 함께 생성되고 트랜잭션에 연결되는 고유한 식별자를 의미합니다. 65 | - 이 식별자는 Master서버 뿐만 아니라 복제 대상에 속하는 Replica(Slave)서버에서도 고유합니다. 66 | - 따라서, Master의 트랜잭션 복제 시 Biglog 파일에 pos 정보 대신에 GTID를 사용하여, master-slave의 일관성을 쉽게 확인 할 수 있습니다. 67 | 68 | ### 참고 자료 69 | [클러스터링, 리플리케이션](https://code-lab1.tistory.com/205) 70 | [레디스 클러스터링](https://velog.io/@tngusqkr1/Redis-cluster-%EC%84%A4%EC%A0%95-1) 71 | [MySQL 리플리케이션 방식](https://hoing.io/archives/3111) 72 | [GTID](https://hoing.io/archives/18445) 73 | -------------------------------------------------------------------------------- /Database/Database, key.md: -------------------------------------------------------------------------------- 1 | # 데이터 베이스 종류와 특징 2 | 3 | DB는 크게 RDB, NoSQL로 분류되고 RDB에는 mysql, oracle 등이있고 4 | noSQL은 몽고디비, 카산드라 등이 있습니다 5 | 이외에도 더많이 존재합니다. 6 | 7 | 특징은 아래와 같습니다. 8 | 9 | - DB는 실시간서비스 되므로 실시간으로 접근할수있다는 특성이있다. 10 | 11 | - DB상태는 계속 변경되고 항상 최신의 데이터를 유지하는 특성이있다. 12 | 13 | - 다수의 사용자가 동시에 같은 내용의 데이터를 이용할수있어야한다. 14 | 15 | - 사용자가 요구하는 데이터 내용으로 데이터를 찾는 특성이있다. 16 | 17 | 18 | # 키 종류와 특징 19 | 20 | - 슈퍼키: 유일성을 만족하는키 (학번+이름, 주민번호+학번) 21 | 22 | - 복합키 : 2개이상의 속성을 사용한키 23 | 24 | - 후보키: 유일성 ,최소성을 만족하는 키 25 | 26 | - 기본키 : NOT NULL, 유일해야한다. 27 | 28 | - 대체 키 : 후보키중 기본키가 아닌키 29 | 30 | - 외래키 : 테이블간 기본키를 참조하는 속성 , 테이블간 관계를 나타내기 위해 사용된다 31 | 32 | 33 | ### 데이터 구조가 자주변하는 데이터를 저장하기위해 RDB, NOSQL중 어떤것이 더 좋을까 34 | 35 | - RDBMS는 스키마를 미리정의하고 데이터타입도 정의하기때문에 구조화된 데이터를 저장하기에 좋고 NOSQL은 데이터 구조에 국한되지않고 데이터를 쉽게 분산저장할수있기때문에 NOSQL이 더 적절하다 36 | 37 | 38 | ### 슈퍼키, 후보키의 관계를 말해주세요 39 | 40 | 슈퍼키는 유일성을 만족하고, 후보키는 유일성, 최소성을 만족한다. 41 | 슈퍼키에서 최소성을 만족하면 후보키이다. 42 | 43 | ### Q) 외래키에 null이 들어갈수있나? 44 | 네 들어갈수있습니다. 그러나 일반적으로 허용하지않습니다. 45 | 최대한 지양해야 참조무결성을 지키는데 좋습니다. 46 | 47 | 48 | 49 | ### Q) nosql에 데이터가 어떻게 저장되는지 설명해주세요 50 | 51 | - Key-value 모델 : Object, JSON 자료형 형식으로 데이터를 쉽게쉽게 저장, 출력이 가능(가장 심플) 52 | 53 | - json Document 모델 : 테이블 대신 Collection이라는 문서 기반으로 데이터 분류, 저장 54 | 55 | - Graph 모델 : 데이터를 노드의 형태로 저장하고 노드간의 흐름 or 관계를 저장할 수 있음 56 | 57 | 58 | ### Q) 로그같은걸 남길때 NOSQL에서 어떤구조를 사용하는게 좋을까? 59 | https://kciter.so/posts/about-mongodb 60 | https://stackoverflow.com/questions/10525725/which-nosql-database-should-i-use-for-logging 61 | https://www.quora.com/Which-NoSQL-database-is-best-for-machine-log-data 62 | 63 | https://www.infoworld.com/article/3263773/how-to-choose-the-right-nosql-database.html 64 | 65 | column model? document model? 66 | 67 | > #### Q) 유일성과 최소성의 의미? 68 | 69 | 유일성: 유니크한 키값으로 하나의 키값으로 투플을 유일하게 식별할수있는 성질 70 | 71 | 최소성: 키를 구성하는 속성중 필요한 속성들로만 최소로 구성하는 성질 72 | 73 | > #### Q) 복합키는 최소성을 만족하나? 74 | 75 | 만족 할수도있고, 안할수도있다. 76 | 관련자료는 찾기힘들었다. 77 | 78 | 79 | ### Q) nosql과 RDB의 차이점 80 | 81 | - nosql은 트랜잭션을 지원하지않고 ACID성질도 가지고있지않다. 82 | - nosql은 테이블구조에 제약을 받지않아서 쉽게 분산저장할수있다. 83 | - RDB는 스키마로 인해 데이터 중복이 없기때문에 update가 많을때 유리할수있다. 84 | - nosql은 대량의 데이터를 빠르게 입출력할때 적합할수있다. 85 | 86 | > #### Q) CAP이론에 대해 설명해주세요 87 | 88 | 분산 DB의 세가지속성인 일관성(Consistency), 가용성(Availability), 분리 내구성(Partition tolerance) 을 나타낸다. 89 | 90 | - Consistency(일관성) 91 | - 모든 노드가 같은시간에 같은 데이터를 보여줘야한다는 의미 92 | - 쓰기동작이 완료된후 발생하는 읽기동작은 마지막으로 쓰여진 데이터를 리턴해야한다는걸 의미한다. 93 | 94 | - Availabilty(가용성) 95 | - 특정 노드가 장애나도 서비스가 가능해야한다 96 | - read,write등은 항상 성공적으로 리턴되어야한다 97 | 98 | - Partitions Tolerance(분리 내구성) 99 | - 노드간에 통신문제가 생겨 메시지를 주고받지 못하더라도 동작해야한다. 100 | - Availabilty는 특정 노드가 장애가 발생한상황이라면 해당특성은 노드의 상태는 정상이지만 네트워크 등의 문제로 연결이 끊어진 상황에대한 이야기다. 101 | 102 | 103 | > #### Q) DBMS가 무엇인가? 104 | 105 | - DB를 관리하는 시스템 106 | - 데이터를 계층또는 탐색 형식으로 저장한다 107 | - 파일시스템을 사용해 저장한다. 108 | - 테이블간 관계가 없다 109 | - 데이터에대한 보안을 제공하지않고, 정규화를 수행할수없어 데이터의 높은 중복성을 가질수있다. 110 | -------------------------------------------------------------------------------- /Database/Normalization.md: -------------------------------------------------------------------------------- 1 | # Normalization (정규화) 2 | 3 | **정규화(Normalization)** 4 | - 정규화의 기본 목표는 **테이블 간에 중복된 데이터를 허용하지 않는다는 것**이며, 중복된 데이터를 허용하지 않음으로써 **무결성(Integrity)를 유지하고, DB의 저장 용량을 줄일 수 있다.** 5 | - 정규화를 하지 않았을 때에는 **이상(Anomaly) 현상**이 발생한다. 6 | 7 | **이상(Anomaly) 현상** 8 | - 이상 현상은 3가지로 구분한다. 9 | 1. **삽입 이상(Insertion Anomaly)** : 튜플 삽입 시 특정 속성에 해당하는 값이 없어 NULL을 입력해야 하는 현상 10 | 2. **삭제 이상(Deletion Anomaly)** : 튜플 삭제 시 같이 저장된 다른 정보까지 연쇄적으로 삭제되는 경우 11 | 3. **갱신 이상(Update Anomaly)** : 속성 값 갱신 시 중복된 데이터의 일부만 갱신되어 정보의 모순이 발생하는 현상 12 | 13 | **함수적 종속성(Functional Dependency)** 14 | - 정규화를 이해하기 전에 함수적 종속성에 대해서 이해 할 필요가 있다. 15 | - 함수 종속성은 어떤 릴레이션 R이 있을 때 X와 Y를 각각 속성의 부분집합이라고 가정했을 때, **X의 값을 알면 Y의 값을 알 수 있고**, **X의 값에 따라 Y의 값이 변경되는 Y는 X에 함수적 종속**이라고 한다. 16 | - **X를 결정자, Y를 종속자**라고 한다. 17 | - 함수적 종속관계에는 **완전 함수적 종속, 부분 함수적 종속, 이행적 함수 종속**이 있습니다. 18 | 1. **완전 함수적 종속** 19 | ![완전 함수적 종속](https://github.com/bombo-dev/CS-JAVA-Study/assets/74203371/43e53522-4a00-4b50-9674-f53ee319e5da) 20 | - 종속자가 **기본키에만 종속되며, 기본키가 여러 속성으로 구성되어 있을 경우 기본키를 구성하는 모든 속성이 포함된 기본키의 부분집합에 종속**된 경우 21 | - 즉, 여러 속성으로 구성되어 있을 경우 **어떠한 속성이 기본키의 최소성을 만족시키는 경우**를 말한다. 22 | 23 | 2. **부분 함수적 종속(Partial Functional Dependency)** 24 | ![부분 함수적 종속](https://github.com/bombo-dev/CS-JAVA-Study/assets/74203371/141efcb0-f4ae-4d7b-84a9-523772b07711) 25 | - 릴레이션에서 종속자가 기본키가 아닌 다른 속성에 종속되거나, 기본키가 여러 속성으로 구성되어 있을 경우 기본키를 구성하는 속성 중 일부만 종속되는 경우 26 | - 즉, 여러 속성으로 구성되어 있을 경우 **어떠한 속성에 대해서 기본키의 최소성을 만족시키지 못하는 경우**를 말한다. 27 | 28 | 3. **이행 함수적 종속(Transitive Functional Dependency)** 29 | ![이행 함수적 종속](https://github.com/bombo-dev/CS-JAVA-Study/assets/74203371/2c653086-6361-42ac-ab16-b9010ddbc104) 30 | - 릴레이션에서 X, Y, Z라는 3개의 속성이 있을 때 **X -> Y, Y -> Z 라는 종속 관계가 있을 경우, X -> Z가 성립될 때**를 말한다. 31 | 32 | ### 제 1 정규화 33 | ![제 1 정규형 위반](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNbQUm%2FbtqT18yag04%2FpTXJX3wB23ouk8az7EgWQ1%2Fimg.png) 34 | - `제 1 정규화`는 **테이블의 컬럼이 원자값(Atomic Value) 즉, 하나의 값을 갖도록 테이블을 분해하는 것**입니다. 35 | - 위 예시는 `제 1 정규형`을 만족하지 못하는 상황입니다. 해당 테이블을 정규화를 수행하게 되면 다음과 같이 변하게 됩니다. 36 | ![제 1 정규화 수행](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMlNZj%2FbtqT17FWVot%2FjUKTAUyOdrH83pRraKw3K0%2Fimg.png) 37 | 38 | ### 제 2 정규화 39 | ![제 2 정규형 위반](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FylbaZ%2FbtqT8Jc4K3s%2F0VFTPoKKFkbxZghKWDwKo1%2Fimg.png) 40 | - **제 1 정규형을 만족하는 테이블에 대해서 완전 함수 종속을 만족하도록 테이블을 분해하는 것**입니다. 즉, **부분 함수 종속을 제거 하는 것**입니다. 41 | - 위 예시는 `제2 정규형`을 만족하지 못하는 상황입니다. 한 강좌가 한 강의실에서만 이루어질 경우, 현재 기본키가 학생번호, 강좌이름으로 구성되어 있을 때 강좌이름 만으로도 강의실을 구분 할 수 있기 때문입니다. 해당 테이블을 정규화를 수행하게 되면 다음과 같이 변하게 됩니다. 42 | ![제 2 정규화 수행](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbluCnc%2FbtqT7VEOf04%2FMe8DfY7rtycgJPYlYQKEWK%2Fimg.png) 43 | 44 | ### 제 3 정규화 45 | ![제 3 정규형 위반](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenwN1N%2FbtqUeiMyErd%2FsP8NKCe70NKsZncGuhO9uK%2Fimg.png) 46 | - **제 2 정규형을 만족하는 테이블에 대해서 이행적 종속을 없애도록 테이블을 분해하는 것**입니다. 즉, **이행 함수 종속을 제거 하는 것**입니다. 47 | - 위 예시는 `제 3 정규형`을 만족하지 못하는 상황입니다. 기본키는 학생 번호이고, 한 명의 학생은 한 가지 강의밖에 듣지 못한다고 가정했을 때, 수강료가 강좌이름에 종속되어 있을 경우, 수강료는 학생번호에도 종속되는 이행종속이 발생되게 됩니다. 해당 테이블을 정규화를 수행하게 되면 다음과 같이 변하게 됩니다. 48 | ![제 3 정규화 수행](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci1le3%2FbtqUeXnPnpD%2FyKkURqr8cZl21f5erx42QK%2Fimg.png) 49 | 50 | ### BCNF 정규화 51 | ![BCNF 정규형 위반](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBN6xu%2FbtqT6IlqRF4%2FMvBoxYMxtgS1JT7t1AymnK%2Fimg.png) 52 | - **제 3정규형을 만족하는 테이블에 대해서 모든 결정자가 후보키가 되도록 테이블을 분해하는 것입니다.** 즉, 테이블 내 모든 속성이 유일성과 최소성을 만족하도록 만드는 정규화입니다. 53 | - 위 예시는 기본키가 학생번호 특강이름으로 이루어졌을 때, 학생번호 특강이름이 교수를 결정합니다. 하지만 교수가 한 가지 강의만 진행한다고 가정했을 때, 교수또한 특강이름의 결정자가 되지만 해당 테이블에서는 중복된 값이 발생해서 유일성을 위배하므로 후보키가 될 수 없습니다. 해당 테이블을 정규화를 수행하게 되면 다음과 같이 변하게 됩니다. 54 | ![BCNF 정규화 수행](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3cbHr%2Fbtq3mNylPan%2Fc6b2lBuH4OkdDNmrzGHWUk%2Fimg.png) 55 | 56 | ### Q) 프로젝트를 진행하면서 정규화 혹은 역정규화의 필요성을 느껴서 해보신 경험이 있다면 얘기해주세요. 57 | - **제 3 정규형**을 위반하여 테이블의 조회 성능을 높인 경험이 있습니다. 통합 테이블 기법을 사용하여 슈퍼타입 서브타입에 대한 공통 부분에 대해서는 유지하고 추가적으로 어떤 세부 타입에 따라 값이 별개로 필요한 상황이었는데, 이때 세부 항목에 대한 필드가 많지 않을 것이라고 판단해서 테이블 내부에 구분하기 위한 Dtype 필드를 명시하고 해당 Dtype 필드에 해당 값들을 종속시켜 해당 값들이 기본 키에도 종속적이지만 Dtype에도 종속적인 이행 종속을 지키지 않았던 경험이 있습니다. 58 | 59 | ### Q) 외래키를 꼭 사용해야 하는지, 아니면 사용하지 않아도 되는지에 대한 의견을 말씀해주세요. 60 | - 외래키를 사용하지 않는 다는 것은 테이블과 관련이 있는 데이터들을 관계로 인한 테이블을 구성하지 않고, 조인에 의한 성능 저하로 인해 한 테이블에 관계를 지정할 수 있는 모든 데이터들을 한 테이블에 넣는 것으로 보입니다. 61 | - 이럴 경우에 해당 테이블이 어떠한 역할을 하는지 파악 하기가 어려우며, 이상현상등이 발생할 가능성이 높고, 또 테이블에 어떠한 필드가 추가되었을 때 수정하기가 어렵다는 단점이 존재합니다. 물론 테이블을 통합 했을 때 필드가 적다면 조인을 하지 않아 조회 성능을 향상 시킬 수 있다는 장점이 있기 때문에, 필드 수 혹은 조인의 횟수에 대해서 고민해서 트레이드 오프를 잘 판단해야 된다고 생각합니다. 62 | 63 | ### Q) 정규화를 계속 진행을 하였을 때의 단점이 무엇인가요? 64 | - 정규화를 계속해서 진행을 한다는 것은 테이블을 계속해서 분할을 하는 것을 의미합니다. 테이블을 계속해서 분할 한 상탸에서 원하는 데이터들을 조회하기 위해서는 조인 기법을 이용하여 테이블을 조회를 해야 합니다. 65 | - 이때, 인덱스가 없는 상황에서 테이블을 조인하게 되었을 때, 어떠한 조인 기법을 택하냐에 따라 다르지만 조인으로 인해 성능저하가 발생합니다. 66 | - 따라서, 정규화를 진행하는 것이 무조건적으로 좋다 라고 말하기는 어렵습니다. 67 | 68 | ### 참고 자료 69 | [[정규화]https://mangkyu.tistory.com/110](https://mangkyu.tistory.com/110) 70 | [[정규화2]https://code-lab1.tistory.com/48](https://code-lab1.tistory.com/48) 71 | [[이상현상]https://code-lab1.tistory.com/47](https://code-lab1.tistory.com/47) 72 | [[함수적 종속]https://dodo000.tistory.com/20](https://dodo000.tistory.com/20) 73 | -------------------------------------------------------------------------------- /Database/Partitioning & Sharding.md: -------------------------------------------------------------------------------- 1 | # 파티셔닝, 샤딩 2 | 파티셔닝 : DB 테이블을 열에 대해서 수직으로 혹은 행에 대해 수평으로 나누는 두 가지 방법으로 작은 부분으로 여러 개 나누는 것 3 | 4 | 샤딩 : 동일한 스키마를 가지고 있는 여러대의 데이터베이스 서버들에 데이터를 작은 단위로 나누어 분산 저장하는 기법 5 | 6 | ### Q) 파티셔닝을 나누는 기준에 대해 설명해주세요. 7 | - `Vertical Partitioning`(수직) : Column 기준 8 | **장점** 9 | - 자주 사용하는 칼럼을 분리하여 성능을 향상할 수 있다. 10 | - 같은 타입의 데이터가 저장되어 데이터 압축률을 높일 수 있다. 11 | - 조회 시 필요 없는 칼럼을 조회하지 않아도 되므로 성능상의 이점이 있다. 12 | 13 | **단점** 14 | - 데이터를 찾는 과정이 기존보다 복잡하므로 Latency 증가 15 | 16 | - `Horizontal Partioning`(수평) : Row 기준 17 | **장점** 18 | - 데이터의 개수를 기준으로 나누어 파티셔닝한다. 19 | - 데이터의 개수와 인덱스의 개수가 줄어들어 성능이 향상된다. 20 | 21 | **단점** 22 | - 데이터를 찾는 과정이 기존보다 복잡하므로 Latency 증가 23 | 24 | ### Q-1) 수직 파티셔닝이 정규화와 비슷한 것 같은데, 무슨 차이가 있을까요? 25 | - 별개로! 정규화는 중복된 데이터를 분리하기 위해 사용, 수직 파티셔닝은 이 테이블에 대해 정규화가 다 끝나고 성능상 이점을 보기 위해 그 때 분리함. 26 | 27 | ### Q-2) 수평 파티셔닝과 샤딩이 비슷한데, 샤딩의 장단점에 대해 설명해주세요. 28 | - 파티셔닝은 모든 데이터를 동일한 컴퓨터에 저장하지만, 샤딩은 데이터를 서로 다른 컴퓨터에 분산한다는 점에서 29 | - 장점 : 부하가 분산됩니다. 30 | - 단점 31 | - 서버를 나눈 것 == 분산된 서버마다 연결해야하므로 수평 파티셔닝보다 접근시간이 더 오래 걸립니다. 32 | - 하나의 서버가 고장났을 때, 문제에 대한 대처가 복잡하다. 데이터 무결성이 지켜지지 않는다. 33 | 34 | ### Q) 샤딩을 어떤 기준으로 해야 효율적일까요? 35 | - 샤딩이란 작은 단위로 나누어 분산 저장하는 기법, 이 때 작은 단위 : 샤드 36 | - Hash Sharding 37 | - PK값의 모듈러 연산 결과를 통해 샤드를 결정하는 방식 38 | - 데이터 개수가 변경될 때 해시 함수도 변경해야하고, 따라서 데이터의 재 정렬이 필요 39 | - 총 데이터베이스 수가 정해져있을 때 유용 40 | 41 | - Range Sharding 42 | - PK 값을 범위로 지정하여 샤드를 지정하는 방식 43 | - Hash Sharding 대비 데이터베이스 증설 작업에 큰 리소스가 소요되지 않는다. 44 | - 특정한 데이터베이스에만 부하가 몰릴 수 있다는 단점 45 | 46 | ### Q) 어떤 경우에 수직 파티셔닝이 쓰이면 좋을까요? 47 | - 조회 시 필요없는 칼럼이 있는 경우, 칼럼을 제외해도 되므로 칼럼별로 분류할 때 사용 가능 48 | - 필요없는 칼럼이 없는 경우, 구할 때 마다 메모리에 값을 올리는 게 부담이 있으므로 자주 사용하는 컬럼만 파티셔닝하여 메모리에 올릴 때 유용유용 49 | 50 | ### Q) 샤딩은 언제 도입을 고려해볼까요? 51 | - 데이터베이스에 들어온 양이 어마무시하게 많을 때 52 | 53 | ### Q) 파티셔닝 종류에 대해 설명해주세요. 54 | ![image](https://github.com/kim-se-jin/CS-JAVA-Study/assets/67494004/e3f474ea-5ea6-4864-9ec8-91922c43b84a) 55 | 56 | **List Partitioning 리스트 파티셔닝** 57 | - 관리자가 직접 지정하는 방식으로 잘 설정한 경우에는 빠른 성능이 보장되지만, 잘못 설정된 경우에는 성능 저하됨. (ex 지역별) 58 | - 많은 SQL에서 해당 칼럼의 조건이 많이 들어오는 경우 유용 59 | 60 | **Range Partitioning 범위 파티셔닝** 61 | - 데이터 내의 특정 범위 내역을 정하여 파티셔닝 해주는 방법 62 | - 장점 : 사용하기 쉬움 63 | - 단점 : 데이터가 균일하게 분포되지 못해서 성능 저하가 생길 수 있다 (ex) 우편 번호, 날짜 등의 데이터에 적합) 64 | 65 | **Hash Partitioning 해시 파티셔닝** 66 | - 파티션 키(Key)의 해시 값에 의한 파티셔닝 67 | - range 파티션에서 범위 분포에 대한 단점을 보완 68 | - hash 함수가 데이터를 균등하게 분포시켜 성능 하락을 방지 69 | - 데이터의 관리가 어렵다는 단점 70 | 71 | **Composite Partitioning 복합 파티셔닝** 72 | - 위 파티셔닝 종류 중 두개 이상을 사용하는 방식 73 | - 큰 파티션에 대한 I/O 요청을 여러 파티션으로 분산할 수 있다. 74 | - 예를 들면 먼저 범위 분할하고, 다음에 해시 분할 같은 것을 생각할 수 있다. 75 | 76 | ### Q-1) 파티셔닝을 사용한다는 것은 데이터를 분리해서 조회 속도를 향상시키기 위함인데, 해시 파티셔닝은 결국 어떤 파티션에 어떤 데이터가 있는 지 모르니 모든 테이블을 찾는 경우가 생길 것 같습니다. 그럼 해시분할은 왜 사용할까요? 77 | - 해시 분할의 경우 mod를 사용하기때문에 mod를 이용해서 값을 찾을 수 있고 키를 문자나 날짜로 설정할 수도 있는데 이럴 경우에는 숫자화를 해준다음 mod를 적절하게 사용해서 찾을 수 있습니다. 78 | 79 | ### Q) 파티셔닝의 3가지 이점에 대해 설명해주세요. 80 | - 테이블 분산을 통해, 쓰기 작업 시 작업이 분산돼 성능이 향상됩니다. 81 | - 물리적으로 여러 테이블로 분산하여 저장되지만, 사용자는 마치 하나의 테이블에 접근하는 것과 같이 사용 82 | - 큰 테이블을 나눠 사용하므로, 관리하기 쉽습니다. 83 | 84 | 85 | -------------------------------------------------------------------------------- /Database/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Database/sql query.md: -------------------------------------------------------------------------------- 1 | ### 쿼리 수행 순서 2 | FROM -> WHERE -> SELECT -> GROUP BY -> HAVING -> ORDER BY -> LIMIT 순으로이루어 져 있다. GROUP BY 의 위치는 무조건 FROM, WHERE 뒤에 위치해야 한다. 3 | 4 | 5 | ### HAVING과 WHERE의 차이를 설명해주세요. 6 | 7 | - 그룹을 나타내는 결과 집합의 행에만 적용된다는 점에서 차이가 있다. 8 | - WHERE 절은 개별 행에 적용됩니다. 쿼리에는 WHERE 절과 HAVING 절이 모두 포함될 수 있다. 9 | 10 | ### group by의 역할에 대해 설명해주세요 11 | 테이블에서 특정 구조로 그룹을 지어주는 역할을 하는 구문 12 | 13 | ### DELETE, TRUNCATE, DROP의 차이를 설명해주세요 14 | 15 | DELETE는 테이블의 컬럼을 삭제할수있고 테이블 용량은 줄어들지않는다.삭제후 되돌릴수없다. 16 | TRUNCATE는 테이블을 용량이 줄어들고 인덱스도 삭제된다. 삭제후 되돌릴수없다. 17 | DROP은 테이블을 삭제한다. 삭제후 되돌릴수없다. 18 | 19 | ### INSERT/ UPDATE/ DELETE/ LIKE/ null 20 | 21 | ```sql 22 | INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...) 23 | 24 | UPDATE 테이블명 SET 컬럼1=컬럼1의 값, 컬럼2=컬럼2의 값 WHERE 대상이 될 컬럼명=컬럼의 값 25 | 26 | DELETE FROM 테이블명 [WHERE 삭제하려는 칼럼 명=값] 27 | 28 | 아디다스로 시작하는 데이터 검색 29 | 30 | select * from tbl_board where title like '아디다스%'; 31 | 32 | 아디다스로 끝나는 데이터 검색 33 | 34 | select * from tbl_board where title like '%아디다스'; 35 | 36 | 아디다스가 들어가는 데이터 검색 37 | 38 | select * from tbl_board where title like '%아디다스%'; 39 | ``` 40 | 41 | #### 평균, 합계, 최고, 최저 42 | ```sql 43 | 합 : select sum(컬럼이름) from 테이블 where 조건 44 | 45 | 평균 : select avg(컬럼이름) from 테이블 where 조건 46 | 47 | 최고 : select max(컬럼이름) from 테이블 where 조건 48 | 49 | 최저 : select min(컬럼이름) from 테이블 where 조건 50 | 51 | ``` 52 | 53 | #### 테이블 정보 54 | ```sql 55 | SHOW TABLE STATUS; 56 | ``` 57 | #### 중복 제거 58 | distinct 59 | 60 | ### **IN, NOT IN 설명** 61 | IN : where 절에서 찾으려는 모든값을 SELECT해준다 62 | NOT IN: 입력한 값을 제외한 값을 SELECT해줄수있게 해준다. 63 | 64 | mysql 기준 65 | ### **숫자에서 문자로** 66 | ```sql 67 | select cast(2 as char(1)); 68 | ```` 69 | ### **문자에서 숫자로** 70 | ```sql 71 | SELECT CAST('123' AS UNSIGNED); 72 | // 문자열을 부호없는 정수형으로 73 | ``` 74 | ### **문자에서 날짜로** 75 | ```sql 76 | STR_TO_DATE('2000-01-31', '%Y-%m-%d') 77 | ``` 78 | ### **날짜 관련 함수** 79 | 너무많아서.. 80 | https://jang8584.tistory.com/7 81 | 82 | ### **분석 함수** 83 | ROW_NUMBER(): 결과에 순번, 순위를 매기는 함수 84 | ```sql 85 | SUM(sal) OVER(PARTITION BY job ORDER BY empno) 86 | ``` 87 | 88 | - **누적 함수** 89 | ```sql 90 | SUM(sal) OVER(PARTITION BY job ORDER BY empno) 91 | ``` 92 | 합을구할때는 SUM만쓰면되는데 조회순서대로 누적할때는 OVER까지 사용한다. 93 | -------------------------------------------------------------------------------- /Java/AccessModifier.md: -------------------------------------------------------------------------------- 1 | # 접근제어자 2 | 3 | ### 1. 접근제어자에 대해서 설명해주세요. 4 | * 접근제어자는 **클래스 또는 클래스의 내부의 멤버들에 사용되어 해당 클래스나 멤버들을 외부에서 접근하지 못하도록 접근을 제한하는 역할을 수행하는 것**입니다. 5 | * 자바에는 **public**, **default**, **protected**, **private** 총 4가지로 구성이 되어 있습니다. 6 | 7 | ![Image](https://i0.wp.com/blog.codestates.com/wp-content/uploads/2022/11/%EC%9E%90%EB%B0%94-%EC%A0%91%EA%B7%BC%EC%A0%9C%EC%96%B4%EC%9E%90-%ED%91%9C.png?w=1312&ssl=1) 8 | 9 | ### 2. DI 사용 시 어떤 접근제어자를 사용하여 개발을 하는가 10 | - 외부 객체에서 내부 객체에 속성에 직접 접근을 하면 안되기 때문에 private를 사용해주어야 하며, 추가적으로 해당 객체 내에 구성클래스가 있는 경우 의존 주입을 무조건 받도록 하는 것이 좋기 때문에 final 키워드를 사용해서 객체 생성 시 컴파일 단계에서 체크하도록 하여 의존 주입을 잊지 않도록 합니다. 11 | 12 | #### Q) 스프링 프레임워크가 없는 세상이라면 DI를 어떻게 구현 할 것인가. 13 | - 클라이언트가 요청 할 때마다 생기는 것이 아닌 애플리케이션이 실행 할 때만 필요한 것이고, 그 클래스의 수가 많지 않다면 직접 new 키워드를 사용해서 직접 주입을 해 줄것이고 그 외에 상황에서는 의존주입 받아야 하는 클래스에 대해서 직접 싱글톤 패턴을 통해 구현을 하고 동시성 처리를 하여 구현을 할 것 같습니다. 14 | - 즉, **IOC(Inversion Of Control, 제어의 역전)** 를 직접 구현해서 사용을 할 것 같습니다. 15 | 16 | **[내용 및 사진 출처]** 17 | - https://www.codestates.com/blog/content/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A7%95 18 | 19 | -------------------------------------------------------------------------------- /Java/CollectionFramework.md: -------------------------------------------------------------------------------- 1 | # 컬렉션 프레임 워크 2 | ### 1. 자바의 컬렉션 프레임워크 란 3 | ![Image](https://hudi.blog/static/1bacac1babc556100455a8c64e7658da/9d567/2.png) 4 | * 컬렉션은 **다수의 요소를 하나의 그룹으로 묶어 효율적으로 저장하고, 관리할 수 있는 기능을 제공하는 일종의 컨테이너** 이다. 5 | * 가변적인 크기를 갖고, 데이터의 삽입, 탐색, 정렬에 대한 편리한 API를 다수 제공한다. 6 | * JDK 1.2 버전부터 java.util 패키지에서 지원하고 이전에도 Vector, Stack, Hash Table 등이 존재했지만 통일성이 없고 표준화 된 인터페이스가 존재하지 않았다. 7 | * 컬렉션 프레임워크에는 크게 리스트(List), 큐(Queue), 집합(Set), 맵(Map)으로 분류 할 수 있다. 8 | 9 | #### Q) Set과 Map은 중복을 허용하지 않는다. 그럼 Set과 Map은 어떤 방식으로 중복을 검사하는가 10 | ```java 11 | public class HashSet extends AbstractSet 12 | implements Set, Cloneable, java.io.Serializable { 13 | // 일부 코드 생략 14 | private transient HashMap map; 15 | 16 | public HashSet() { 17 | map = new HashMap<>(); 18 | } 19 | } 20 | ``` 21 | - Set과 Map 둘 다 동일하게 HashTable을 사용합니다. 22 | **Map은 형식으로 Value에 값이 들어가 있는 경우가 많습니다.** 23 | **Set은 무조건 로 저장**합니다. 해시 함수에 대한 HashValue를 키로 사용함으로써, 동일한 키가 존재하면 equals() 메서드를 통해 중복된 값인지 확인합니다. 24 | #### Q) 만약 사용자가 정의한 타입이면 어떻게 같은지를 구분하는가 25 | - 사용자가 정의한 Reference type은 Object에 구현되어 있는 동등성 비교(Equals)와 hashcode() 오버라이딩 함으로써 객체가 동일한지 판단할 수 있도록 해줍니다. 26 | #### Q) hashcode()의 default 값은 무엇인가요? 27 | - hashCode의 구현부는 JDK에 달려있다고 합니다. 대체적으로 객체의 메모리 주소라고 많이 알려져있는데, 그렇지 않다고 합니다. 28 | 29 | #### Q) HashMap, LinkedHashMap, TreeMap에 대해서 설명해주세요. 30 | - **HashMap**은 가장 기본적인 Map 자료구조로 `` 로 구성되어 있습니다. 하지만 iterator를 사용하여 **출력 시 순서가 보장되지 않습니다.** 31 | - **LinkedHashMap**은 HashMap에서 순서가 보장되지 않는 단점을 해결하여 **순서가 보장**되도록 하는 Map 자료구조입니다. 32 | - **TreeMap**은 Map에 저장 된 키에 대해서 **이진 트리를 기반으로 정렬**되어 있는 Map 자료구조를 말합니다. 33 | 34 | #### Q) 세 가지 Map 자료구조에 대해서 어떤 것을 더 자주 사용하는가 35 | - HashMap을 사용합니다. Map 자료구조는 ``를 통해 찾고자 하는 값을 O(1) 로 찾아낼 수 있다는 장점이 있습니다. Linked 혹은 Tree는 부가적인 기능이 추가된 것이여서, 만약 필요하다면 다른 컬렉션을 사용 할 것 같습니다. 36 | #### Q) HashMap, LinkedHashMap, TreeMap에 탐색에 대한 속도 차이가 존재하는가 37 | - HashMap, LinkedHashMap 같은 경우에는 O(1) 만큼 동일하게 소요되지만, LinkedHashMap 같은 경우에는 Linked-list를 유지하는 비용이 추가로 발생됩니다. 38 | - TreeMap은 RedBlackTree로 구성되어 있고, 트리로 구성되어서 삽입, 탐색하는데 O(logN) 만큼의 시간이 소요됩니다. 39 | 40 | #### Q) HashMap, HashTable, ConcurrentHashMap의 차이점 41 | **[HashMap]** 42 | - HashMap은 **동기화 처리를 하지 않는 자료구조이기에 Thread-safe 하지 않습니다. 43 | - **싱글 쓰레드 환경에서 사용**을 해야합니다. 44 | - 동기화 처리를 하지 않아 **HashTable과 ConcurrentHashMap에 비해 데이터를 찾는 속도가 빠릅니다.** 45 | 46 | **[HashTable]** 47 | - HashTable이 HashMap 보다 먼저 나왔는데, **HashTable은 동기화 처리**가 되어있습니다. 48 | - HashMap은 key와 value에 null을 허용하는 반면, **HashTable은 null을 허용하지 않습니다**. 49 | - **인스턴스 메서드에 synchronized** 가 걸려있습니다. 50 | ```java 51 | public synchronized V put(K key, V value) { 52 | if (value == null) { 53 | throw new NullPointerException(); 54 | } 55 | 56 | Entry tab[] = table; 57 | int hash = key.hashCode(); 58 | int index = (hash & 0x7FFFFFFF) % tab.length; 59 | @SuppressWarnings("unchecked") 60 | Entry entry = (Entry)tab[index]; 61 | for(; entry != null ; entry = entry.next) { 62 | if ((entry.hash == hash) && entry.key.equals(key)) { 63 | V old = entry.value; 64 | entry.value = value; 65 | return old; 66 | } 67 | } 68 | 69 | addEntry(hash, key, value, index); 70 | return null; 71 | } 72 | ``` 73 | 74 | **[ConcurrentHashMap]** 75 | - ConcurrentHashMap은 **HashTable의 동기화 성능을 최적화 한 자료구조**입니다. 76 | - HashTable은 메서드 자체에 동기화 처리를 하였지만, **ConcurrentHashMap은 동기화 블럭을 사용하여 한 Entry에 대해서만 동기화**가 이루어집니다. 77 | 78 | #### Q) ArrayList, LinkedList를 각각 어떤 상황에서 사용 할 것인가 79 | - ArrayList는 인덱스를 가지고 있어 인덱스로 조회를 하는 경우에 빠르게 사용 할 수 있다는 장점이 있습니다. 하지만 중간에 값을 추가하거나 삽입하는 과정에서 쉬프트로 인해 많은 비용이 발생하고 데이터가 추가되는 과정에서 GC와 백업에 대한 연산에 있어서도 추가적인 비용이 발생 할 수 있어 정적인 조회가 많은 경우에 사용합니다. 80 | - LinkedList는 ArrayList와 달리 중간 삽입, 삭제 연산이 빠르지만 탐색 속도가 ArrayList에 비해서 떨어지기때문에 중간 삽입, 삭제 연산이 많다면 LinkedList를 사용합니다. 81 | 82 | #### Q) ArrayList의 capacity가 꽉찼을 경우에 발생하는 일을 설명해주세요. 83 | - ArrayList는 capacity가 초과되면 데이터를 백업하고 메모리 공간을 비웁니다. 이 과정에서 GC가 발생하고, 추가적인 메모리 공간을 늘려 새로운 메모리 공간에 다시 데이터를 적재합니다. 84 | 85 | #### Q) HashMap의 충돌에 대해서 설명해주세요. 86 | - 자바에서는 해시 충돌에 대해서 Separate Chaning 방식을 택하고 있고, 하나의 해시버킷에 8개의 키-값 쌍이 모이면 RB Tree로 변경됩니다. 87 | 88 | #### Q) 해시 충돌에 확률을 줄이기 위한 방법 89 | - 자바에서는 해시 버킷의 개수의 기본값은 16이고 임계점(loadFactor 0.75)에 도달 할 때마다 버킷 개수의 크기를 두 배씩 증가시킵니다. 버킷의 최대 개수는 2^30 입니다. 90 | - 하지만 이때, 해시 버킷의 개수가 2^a 형태가 되므로 보조 해시 함수의 % M 을 사용할 경우 하위 a개의 비트만 사용하게 되어서 해시 충돌이 쉽게 발생할 수 있다는 문제가 있습니다. 91 | 92 | - 자바에서는 해시 충돌을 줄이기 위해 보조 해시 함수를 사용하고 있고, java 7 에서는 다음과 같은 보조 해시 함수를 사용하였습니다. 93 | ```java 94 | final int hash(Object k) { 95 | // Java 7부터는 JRE를 실행할 때, 데이터 개수가 일정 이상이면 96 | // String 객체에 대해서 JVM에서 제공하는 별도의 옵션으로 97 | // 해시 함수를 사용하도록 할 수 있다. 98 | // 만약 이 옵션을 사용하지 않으면 hashSeed의 값은 0이다. 99 | int h = hashSeed; 100 | if (0 != h && k instanceof String) { 101 | return sun.misc.Hashing.stringHash32((String) k); 102 | } 103 | h ^= k.hashCode(); 104 | // 해시 버킷의 개수가 2a이기 때문에 해시 값의 a비트 값만을 105 | // 해시 버킷의 인덱스로 사용한다. 따라서 상위 비트의 값이 106 | // 해시 버킷의 인덱스 값을 결정할 때 반영될 수 있도록 107 | // shift 연산과 XOR 연산을 사용하여, 원래의 해시 값이 a비트 내에서 108 | // 최대한 값이 겹치지 않고 구별되게 한다. 109 | h ^= (h >>> 20) ^ (h >>> 12); 110 | return h ^ (h >>> 7) ^ (h >>> 4); 111 | } 112 | ``` 113 | - java 8 부터는 굉장히 단순해졌는데 해시 값과 해시 값에 대한 시프트 연산으로 >>> 16 만큼 이동한 값과 XOR 연산을 통한 보조 해시 함수를 사용하고 있습니다. 114 | ```java 115 | static final int hash(Object key) { 116 | int h; 117 | return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 118 | } 119 | ``` 120 | 121 | ### 참고 이미지 122 | - [사진1](https://hudi.blog/java-collection-framework-1/) 123 | - [Hash 참고자료](https://d2.naver.com/helloworld/831311) -------------------------------------------------------------------------------- /Java/Error & Exception.md: -------------------------------------------------------------------------------- 1 | # Error & Exception 2 | 자바의 예외는 크게 3가지로 나눌 수 있습니다. 3 | 4 | ![image](https://user-images.githubusercontent.com/76711238/236800636-d2964fe2-27ff-4bb8-9e92-9639b266120f.png) 5 | 6 | - 1. **에러(Error)**: 7 | - 에러(Error)는 시스템에 무엇인가 비정상적인 상황이 발생한 경우에 사용됩니다. 주로 자바 가상 머신에서 발생시키는 것이며 예외와 반대로 이를 애플리케이션 코드에서 잡을 수 없습니다. 8 | - (ex) 메모리 부족(OutofMemoryError), 스택오버플로우(StackOverflowError) 9 | 10 | - 2. **예외** 11 | - 예외(Exception)란 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중에 참조된 값이 잘못된 경우 등 정상적인 프로그램의 흐름을 어긋나는 것을 말합니다. 자바에서 예외는 개발자가 직접 처리할 수 있기 때문에 예외 상황을 미리 예측하여 핸들링할 수 있습니다. 12 | 13 | > 컴파일러가 에러처리를 확인하지 않는 RuntimeException 클래스들은 unchecked 예외라고 부르고 14 | 예외처리를 확인하는 Exception 클래스들은 checked 예외라고 부릅니다. 15 | 16 | - 2-1. **체크 예외(Checked Exception)** : 17 | - Checked Exception은 RuntimeException을 상속하지 않은 클래스입니다. 18 | - 명시적인 예외 처리를 해야 합니다. 19 | - 컴파일 시점에 확인할 수 있습니다. (=> 따라서 반드시 에러 처리를 해야하는 특징(try/catch or throw)을 가집니다. ) 20 | - 트랜잭션 안에서 동작할 때 Checked Exception이 발생하면 Rollback 되지 않는다는 특징이 있습니다. 21 | - **기본적으로 Checked Exception은 복구가 가능하다는 메커니즘** 을 가집니다. 22 | - 복구가 가능하니 트랜잭션 도중 에러가 발생하더라도 롤백이 발생하지 않습니다. 23 | - 예를 들어, 특정 이미지 파일을 찾아서 전송해 주는 함수에서 이미지를 찾지 못 했을 경우 기본 이미지를 전송한다는 복구 전략을 가질 수 있습니다. 24 | - 즉, **복구가 가능하니 Rollback은 진행하지 않는다**는 의미이다. 25 | - (ex) 존재하지 않는 파일의 이름을 입력(FileNotFoundException) 26 | 실수로 클래스의 이름을 잘못 적음(ClassNotFoundException) 27 | 28 | - 2-2. **언체크 예외(Unchecked Exception)** : 29 | - Unchecked Exception은 RuntimeException을 상속한 클래스입니다. 30 | - 명시적인 예외 처리를 하지 않습니다. 즉, 에러 처리를 강제하지 않습니다. 31 | - 런타임 시점에 확인할 수 있습니다. ( RuntimeException의 하위 클래스이기에 실행 중에(runtime) 발생할 수 있는 예외를 의미합니다. ) 32 | - 트랜잭션 안에서 동작할 때 Unchecked Exception이 발생하면 롤백된다는 특징이 있습니다. 33 | - (ex) 열의 범위를 벗어난(ArrayIndexOutOfBoundsException) 34 | 값이 null이 참조변수를 참조(NullPointerException) 35 | 36 | ![image](https://user-images.githubusercontent.com/76711238/236801670-80cb9e99-a32c-4571-96d5-f6260598eba6.png) 37 | 38 | 39 | ### Q) Checked Exception 과 Unchecked Exception 의 transaction 예외 처리 방식을 설명해주세요. 40 | - Checked Exception : 기본적으로 commit 이 됩니다. (무조건 처리돼야 하는 exception) 41 | - Unchecked Exception : rollback 이 됩니다. (무조건 처리돼야 하지 않아도 되는 exception) 42 | 43 | ### Q-1) @Transactional 는 어떻게 구현되나요? 44 | - proxy 원리를 사용해서 구현됩니다. 45 | - 프록시 패턴을 사용하는 이유 : 프록시 객체는 원래 객체를 감싸고 있는 객체로, 원래 객체와 타입은 동일합니다. 프록시 객체가 원래 객체를 감싸서 client의 요청을 처리하게 하는 패턴입니다. 46 | - 프록시 패턴을 통해 접근 권한을 부여할 수 있습니다. 47 | - 프록시 패턴을 통해 부가 기능을 추가할 수 있습니다. 48 | ### Q-2) @Transactional 이 붙지 않은 메소드의 내부에서 @Transactional 이 붙은 메소드를 사용할 시, 이 내부 메소드도 @Transactional이 적용될까요? 49 | - 적용되지 않습니다. 50 | - 예시는 아래와 같습니다. 51 | 52 | ```java 53 | public class BookImpl implements Books { 54 | public void addBooks(List bookNames) { 55 | bookNames.forEach(bookName -> this.addBook(bookName)); 56 | } 57 | 58 | @Transactional 59 | public void addBook(String bookName) { 60 | Book book = new Book(bookName); 61 | bookRepository.save(book); 62 | book.setFlag(true); 63 | } 64 | } 65 | ``` 66 | - 위와 같은 상황에서 addBooks메서드의 내부에서 호출하는 addBook 메서드의 @Transactional 어노테이션이 적용되지 않습니다. 67 | 68 | - Spring은 AOP를 이용해 `@Transactional` 어노테이션을 선언한 메서드가 실행되기 전 transaction begin을 삽입하고, 메서드 실행 후에 Transaction commit 코드를 삽입하여, 객체 변경감지를 수행하도록 유도합니다. 69 | 70 | - Spring의 코드 삽입 방식은 크게 2가지가 있습니다. 71 | 72 | - 1) 바이트 코드 생성(CGLIB) 73 | - 2) 프록시 객체 사용 74 | - 2가지 방법 중에 Spring은 기본적으로 프록시 객체 사용 방식을 선택합니다. (SpringBoot는 기본적으로 바이트 코드 생성 방식 사용) 75 | 76 | - 원리는 아래 코드와 같습니다. 프록시 객체로 우리가 만든 메서드를 한번 감싸서, 메서드 위 아래로 코드를 삽입합니다. 77 | 78 | ```java 79 | public class BooksProxy { 80 | private final Books books; 81 | private final TransactonManager manager = TransactionManager.getInstance(); 82 | 83 | public BooksProxy(Books books) { 84 | this.books = books; 85 | } 86 | 87 | public void addBook(String bookName) { 88 | try { 89 | manager.begin(); 90 | books.addBook(bookName); 91 | manager.commit(); 92 | } catch (Exception e) { 93 | manager.rollback(); 94 | } 95 | } 96 | } 97 | ``` 98 | - 위와 같은 코드로 인해 우리가 BookImpl클래스를 사용할 때, 스프링이 제공하는 BookProxy 객체를 사용하게 되며, 프록시 객체가 제공하는 addBook 메서드를 사용해야만 트랜잭션 처리가 수행되게 됩니다. 99 | 100 | - **@Transactional이 수행되지 않은 이유** 101 | - BooksProxy 가 addBooks 메서드를 수행하면, 아래와 같은 순서로 작동됩니다. 102 | - `BookProxy::addBooks -> BooksImpl::addBook` 103 | 104 | - 즉, **프록시 객체가 아닌 실제 BookImpl 객체의 함수를 호출하게 되므로 해당 메서드는 트랜잭션으로 감싸지지 않은 상태**로 @Transactional 어노테이션 기능이 수행되지 않는 것입니다. 105 | 106 | - **해결 방법** 107 | - 1. @Transactional 어노테이션 메서드는 클래스 내부적으로 사용하지 말고, 밖에서 사용합니다. (권장) 108 | - 2. 굳이 내부적으로 사용하려면, 자기 자신의 Proxy 객체를 사용하여 처리합니다. (아래 코드 참조) 109 | 110 | ```java 111 | @Service 112 | public class BooksImpl implements Books { 113 | @Autowired 114 | private Books self; 115 | 116 | public void addBooks(List bookNames) { 117 | bookNames.forEach(bookName -> self.addBook(bookName)); // this 가 아닌 변수 self 로 118 | } 119 | 120 | @Transactional 121 | public void addBook(String bookName) { 122 | Book book = new Book(bookName); 123 | bookRepository.save(book); 124 | book.setFlag(true); 125 | } 126 | } 127 | ``` 128 | - 위 코드는 Books 인터페이스를 이용하여 BooksProxy 인스턴스를 주입할 수 있도록 유도합니다. 129 | - 그 후, 프록시 객체의 addBook 메서드 사용을 통해 @Transactional 어노테이션 기능을 사용할 수 있게 합니다. 130 | 131 | #### 사진 & 내용 출처 132 | 133 | https://steady-coding.tistory.com/583 134 | 135 | https://velog.io/@chullll/Transactional-%EA%B3%BC-PROXY 136 | 137 | https://velog.io/@ddongh1122/Spring-Transactional-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%82%B4%EB%B6%80-%ED%98%B8%EC%B6%9C-%EB%AF%B8%EC%9E%91%EB%8F%99-%EC%9D%B4%EC%8A%88 138 | -------------------------------------------------------------------------------- /Java/GC.md: -------------------------------------------------------------------------------- 1 | # GC 2 | 가비지 컬렉터은 가바 가상 머신내의 실행 엔진 영역에 존재합니다. 3 | **Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체**(garbage)를 모아 **주기적으로 제거**하는 프로세스입니다. 4 | - 여기서 동적으로 할당했던 메모리 영역 : 프로그램 런타임에 사용되는 Heap 영역 메모리 5 | - 필요 없게 된 영역 : 어떤 변수도 가리키지 않게 된 영역 6 | 7 | ### Q) GC의 작동원리에 대해 설명해주세요. 8 | - ### Q-1) 언제 GC가 작동될까요? ( = Garbage가 될 때 ) 9 | - 참조되는 객체가 **더 이상 참조되지 않을 때** GC 처리를 합니다. 10 | 11 | - ### Q-2) GC의 내부 작동 원리 12 | ![image](https://user-images.githubusercontent.com/67494004/234883381-816208ba-528c-4cb7-b668-d3a075e5e416.png) 13 | - GC는 Young 영역과 Old 영역으로 나눠져 있습니다. 14 | 15 | #### Young 영역 16 | - **새롭게 생성된 객체가 할당되는 영역**입니다. Young영역에 대한 GC를 **Minor GC**라고 부릅니다. 17 | - Eden, Survivor0, Survivor1 으로 나뉨 18 | - **Eden** 19 | - new를 통해 새로 생성된 객체가 위치 20 | - 정기적인 쓰레기 수집 후 살아남은 객체들은 Survivor 영역으로 보냄 21 | - **Survivor 0/1** 22 | - 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역 23 | - Survivor 0 또는 Survivor 1 둘 중 하나에는 꼭 비어 있어야 함 24 | - 만약 두 Survivor 영역에 모두 데이터가 존재하거나, 모두 사용량이 0이라면 현재 시스템이 정상적인 상황이 아님 25 | 26 | - ### Q) 왜 Survivor 영역은 2개 인가요? 27 | ![image](https://user-images.githubusercontent.com/67494004/234882564-c23d4d0d-e27b-4997-801e-dbdf99cd6b0f.png) 28 | - 외부 단편화 문제를 해결하기 위해서 입니다. 메모리가 할당되고 헤제되기를 반복하다 보면 왼쪽 사진과 같이 총 메모리 공간은 남지만, 29 | 파편화되어있어 메모리를 할당할 수 없는 문제가 발생합니다. (외부 단편화) 30 | 31 | > 💡 **age !** 32 | - minorGC 때 garbage되어 사라지지 않고, **Survivor영역에서 살아남은 횟수를 의미하는 값**입니다. **age 값이 임계값에 다다르면 Promotion(Old 영역으로 이동) 여부를 결정**합니다. 33 | - Object Header에 기록됨 34 | - JVM 중 가장 일반적인 HotSpot JVM age의 기본 임계값 : 31 35 | - 객체 헤더에 age를 기록하는 부분이 6 bit로 되어 있기 때문 36 | 37 | 38 | #### Old 영역 39 | - Young영역에서 Reachable 상태를 유지하여 **살아남은 객체가 복사되는 영역**입니다. 40 | - Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생합니다. 41 | - old 영역에 대한 가비지 컬렉터(Garbage Collection)을 **Major GC** 또는 Full GC라고 부릅니다. 42 | - **Young에서 처리할 수 없을 정도로 큰 경우, 바로 Old Generation** 43 | 44 | #### Meta Space 영역 45 | ![java7 8](https://user-images.githubusercontent.com/67494004/234877495-d4a322b5-dc94-4b78-b55d-da2806715cf7.JPEG) 46 | - **자바 8 이전** : **Permanation 영역** - Heap 영역에 위치 47 | - **자바 8 이후** : **MetaSpace 영역** - Native Memory 영역에 위치 48 | 49 | - 저장하는 데이터 : 자바의 메타 데이터 50 | - Class Meta Data 51 | - Method Meta Data 52 | - Static Object Variable 53 | 54 | 💡 **PermGen 제거된 이유 ? ( = 단점 )** 55 | - PermGen 영역이 **고정 크기**로 할당되어 있기 때문에, 할당 가능한 메모리 크기가 제한적입니다. 56 | - 클래스 메타데이터가 많아지면, PermGen 영역의 **메모리 부족으로 인해 OutOfMemory(OOM) Error 가 발생**할 수 있습니다. 57 | - PermGen 영역의 GC는 **Full GC** 를 수행하기 때문에, GC 가 길어집니다. 58 | 59 | 💡 이를 보완한 MetaSpace 60 | - Metaspace 영역은 JVM에 의해 관리되는 Heap이 아닌 OS 레벨에서 관리되는 Native Memory 영역 61 | - 운영체제가 메모리를 동적할당하는 방식으로 변경 62 | - 그러므로 Metaspace가 Native 메모리를 이용함으로서 개발자는 영역 확보의 상한을 크게 의식할 필요가 없어지게 됨! 63 | - 메모리의 동적할당으로 이루어지기 때문에 메모리 단편화를 방지하기 위하여 블록 할당방식으로 변경되었으며 메타데이터의 정보는 힙과 네이티브 메모리 두 영역에 모두 할당 64 | 65 | 66 | ### Q) Young/Old 영역을 나누는 이유? 67 | - Heap 영역은 처음 설계될 때 다음의 2가지 전재로 설계되었습니다. 68 | - 대부분의 객체는 금방 접근 불가능한 상태가 된다. 69 | - 오래된 객체에서 새로운 객체로의 참조는 아주 적개 존재한다. 70 | - 즉, **객체는 대부분 일회성이며, 메모리에 오래 남아있는 경우가 드물기 때문에** 생존 기간에 따라 **객체를 효율적으로 관리**하기 위해 나눕니다. 71 | 72 | ### Q) Minor GC와 MajorGC 의 차이점에 대해 말씀해주세요. 73 | - 소요 시간 입니다. Young 영역은 크기가 작기때문에 Minor GC 적은 시간, Old 영역은 크기가 크기 때문에 MajorGC는 오래 걸립니다. 74 | 75 | ### Q-1) Stop the World 에 대해 설명해주세요. 76 | - Stop the world는 GC를 수행하기 위해 어플리케이션 자체를 멈추는 현상을 말합니다. GC는 자신을 제외한 모든 스레드를 모두 멈추기 때문에 차질이 생길수도 있습니다. 77 | 78 | ### Q-2) 왜 다른 스레드들은 모두 종료해야 할까요? 79 | - Heap의 상태가 변경될 수 있기 때문에 중단하고, 값을 변경해야 합니다. 80 | 81 | ### Q) Old 영역의 객체는 Young 영역의 객체를 참조하는 경우가 있습니다. 이럴 경우, Eden 영역에서 GC가 실행되면, Old 영역이 참조하고 있는 객체는 지우면 안됩니다. List형식으로 순차적으로 확인해야하는데, 개선하기 위한 방법을 JVM이 보유한 방법에 대해 설명해주세요. 82 | > Hint💡 Table 83 | - Old영역에 512bytes 크기의 Card Table 이 있습니다. 84 | - Card Table 85 | - **old 영역에 있는 객체가 Young 영역을 참조할 때 마다 그에 대한 정보가 표시**됩니다. 86 | - **Minor GC**가 실행될 때, 모든 Old영역에 존재하는 객체를 검사하는 것은 비효율적임, Young 영역에서 GC가 진행될 때 **카드 테이블만 조회**하여 GC의 대상인 지 식별합니다. 87 | 88 | ### Q) 가장 인상깊었던 Garbage Collection 알고리즘에 대해 설명해주세요. 89 | **CMS GC (Concurrent Mark Sweep)** 90 | ![gc_cms](https://user-images.githubusercontent.com/67494004/234877620-6b0603c5-5546-4271-a335-2776a4e1695e.png) 91 | - 애플리케이션의 지연 시간을 최소화 하기 위해 고안되었으며, 애플리케이션이 구동중일 때 프로세서의 자원을 공유하여 이용 가능한 알고리즘 92 | - Mark Sweep 알고리즘을 **Concurrent하게 수행** 93 | - ❌ 단점 : 다른 GC 방식보다 메모리와 CPU를 더 많이 필요로 하며, Compaction 단계를 수행하지 않음. 94 | - 시스템이 장기적으로 운영되다가 조각난 메모리들이 많아 Compaction 단계가 수행되면 오히려 **Stop The World 시간이 길어지는 문제가 발생** 95 | 96 | **G1(Garbage First) GC** 97 | 98 | 99 | ![image](https://user-images.githubusercontent.com/67494004/234877925-d83cefe4-f19f-40cf-b78d-1cd11c0ce2df.png) 100 | - 장기적으로 많은 문제를 일으킬 수 있는 CMS GC를 대체하기 위해 개발 101 | - **Region(지역)이라는 개념**을 새로 도입하여 **Heap을 균등하게 여러 개의 지역**으로 나누고, **각 지역을 역할과 함께 논리적으로 구분**하여(Eden 지역인지, Survivor 지역인지, Old 지역인지) 객체를 할당 102 | - Heap을 동일한 크기의 Region으로 나누고, 가비지가 많은 Region에 대해 우선적으로 GC를 수행 103 | 104 | 105 | ### Q) static을 잘못쓰면 Memory Leak 이 발생할 수 있는데, 자바 GC와 연관지어 설명해주세요. 106 | - Memory Leak은 프로그램에서 동적으로 할당한 메모리 공간을 반환하지 않는 경우 발생할 수 있는 문제 입니다. 개발자가 객체를 생성하고 사용한 후, 메모리를 반환하지 않는 경우에 발생합니다. 107 | 108 | - (질문자 예시) 가변적인 자료구조 앞에 static을 붙이는 경우 109 | - static 으로 hashMap이 있다고 쳤을 때 할당 해제가 되지 않아 memory leak 발생 110 | - 참조가 안되어있으면 GC 가 발동이 되어야하는데, static을 사용함으로 인해 Memory에 계속 남아있게 됨. 111 | 112 | - static을 사용하게 되면 compile과 동시에 method영역에 객체가 할당되게 됩니다. 사용되지 않는데 메모리에 계속 남아있다면 메모리 낭비이기 때문에 GC가 안쓰는 걸 확인하고 비워줌으로 메모리를 효율적으로 사용할 수 있습니다. 113 | 114 | ### Q) 자바8부터 static이 저장되는 영역이 바꼈는데, static은 어디에 저장될까요? 115 | 116 | - MetaSpace영역 입니다. 117 | - Method Area : 클래스 정보와 메서드 코드를 저장 118 | - Metaspace : 클래스 메타데이터를 저장 119 | 120 | > [추가 참고] 121 | > class meta-data가 metaspace로 이동하고 기존에 perment 영역에 저장되던 static object는 heap영역에 저장되도록 변경되었다고 설명하는데 이는 reference는 여전히 metaspace에서 관리됨을 의미하기에 참조를 잃은 static object는 GC의 대상이 될 수 있으나 reference가 살아있다면 GC의 대상이 되지 않음을 의미한다. 122 | > 123 | > 124 | > 따라서, metaspace는 여전히 static object에 대한 reference를 보관하며 애매하게 heap에 걸쳐지지 않고 non-heap(native memory)로 이관되며 static 변수(primitive type, interned string)는 heap 영역으로 옮겨짐에 따라 GC의 대상이 될 수 있게끔 조치한 것이다. 125 | 126 | - ### Q-1) static은 결국 heap으로 옮겨졌으면, 결국 GC가 될 수 있는 거 아닌가요? 127 | - **null 선언 시** 사용하지 않는 객체로 GC가 가능해집니다. 128 | 129 | ### Q) JVM도 되게 다양한데, 그 중 Hotspot JVM 이 기존의 Mark-And-Sweep 을 개선하였는데 알고 계시면 설명해주세요. 130 | > Hint💡 Bump the Pointer, TLABs 131 | - **Bump the pointer** 란 132 | - **Eden영역에 마지막으로 할당된 객체의 주소를 캐싱**해두는 것 입니다. 133 | - 새로운 객체를 위해 유효한 메모리를 탐색할 필요없이 마지막 주소의 다음 주소를 사용하게 함으로써 **속도를 높일** 수 있습니다. 134 | - 이를 통해 새로운 객체를 할당할 때 객체의 크기가 Eden영역에 적합한지만 판별하면 되므로 빠르게 메모리를 할당할 수 있습니다. 135 | 136 | 멀티쓰레드 환경인 경우, Eden영역에 할당할 때 동기화가 필요합니다. **멀티쓰레드 환경에서 성능 문제를 해결하기 위해 TLABs 가 도입**되었습니다. 137 | 138 | - **TLABs(Thread Local Allcation Buffers)** 란 139 | - **각각의 스레드마다 Eden영역에 객체를 할당하기 위한 주소를 부여함**으로써 동기화 작업 없이 빠르게 메모리를 할당하는 기술입니다. 140 | - 각각의 쓰레드는 자신이 갖는 주소에만 객체를 할당함으로써 동기화없이 bump the pointer를 통해 빠르게 객체를 할당할 수 있습니다. 141 | 142 | ### Q) Traffic 이 몰릴 것으로 예상되는 이벤트가 예정되어 있습니다. 여기서 Young 과 Old 영역의 비율을 튜닝할 수 있는데, 어떤 비율로 튜닝해야 할까요? 143 | > Plus💡 기존 default값 **Young 1 : Old 3** 144 | 145 | ##### 1.먼저 **트래픽의 특성을 파악**해야 합니다. 146 | - Young 영역은 적은 크기의 객체를 빠르게 처리하는 데 사용되며, Old 영역은 큰 크기의 객체를 처리하는 데 사용됩니다. 147 | 148 | ##### 2-1. **짧은 시간동안 대량의 작은 객체가 생성되는 경우** 149 | - **Young 영역의 크기를 늘리고** Old 영역의 크기를 줄여서 Young GC가 더 자주 발생하도록 설정하는 것이 좋습니다. 작은 객체를 더 빠르게 처리하고 메모리를 효율적으로 사용할 수 있습니다. 150 | - Young 영역의 크기를 늘리면 Major GC 빈도가 줄어들기 때문에 가비지 수집기의 성능이 향상될 수 있습니다. 151 | - == 마이너 GC가 더 자주 발생할 수 있음 152 | 153 | ##### 2-2. **대량의 큰 객체가 생성되는 경우** 154 | - **Old 영역의 크기를 늘려** GC가 덜 발생하도록 설정하는 것이 좋습니다. 이렇게 함으로써 큰 객체를 더 효율적으로 처리하고 메모리를 효율적으로 사용할 수 있습니다. 155 | - Old 영역의 크기를 늘리면 Major GC의 빈도를 줄일 수 있지만, Major GC의 일시 중지 시간이 길어질 수 있음 156 | 157 | ##### 3.**결론** 158 | - 따라서 예상되는 트래픽의 특성을 고려하여 Young 영역과 Old 영역의 비율을 조정하면, GC 성능을 최적화할 수 있습니다. 159 | - 응용 프로그램이 수명이 짧은 개체를 많이 생성하는 경우 Young 영역의 크기를 늘리는 것이 좋습니다. 160 | - 응용 프로그램에 수명이 긴 개체가 많은 경우 Old 영역의 크기를 늘리는 것이 좋습니다. 161 | 162 | 163 | --- 164 | 165 | _**스터디 진행 시 대답과 꼬리질문**_ 166 | (꼬리질문이 좋아서 넣어봤습니다 ㅎㅎ ) 167 | 168 | - 먼저 Young 영역의 비중을 늘릴 것 입니다. 트레픽이 몰린다는 것은 많은 유저가 들어온다는 뜻이므로, 금방 생성되었다 사라지는 객체가 많을 것 같기 때문에 3:1 로 하겠습니다. 169 | 170 | - ### Q-1) 그럼 Young 영역을 높인다는건데, 영역이 크기가 커지면 Stop-the-World 시간도 길어지고 수거해야할 객체가 많아지지 않을까요? 171 | - Young 영역과 Old영역을 늘렸을 때의 Trade-off 설명 172 | 173 | 174 | 175 | 176 | ### 참고 177 | [내용 및 사진-1](https://inpa.tistory.com/entry/JAVA-☕-JVM-내부-구조-메모리-영역-심화편#가비지_컬렉터_garbage_collector_,gc) 178 | [내용 및 사진-2](https://flightsim.tistory.com/240) 179 | [MetaSpace 내용-1](https://goodgid.github.io/Java-8-JVM-Metaspace/) 180 | [MetaSpace 내용-2](https://velog.io/@agugu95/자바-런타임-환경과-메모리-Java-Heap-Permgen-and-MetaSpace) 181 | [GC 알고리즘](https://mangkyu.tistory.com/119) 182 | [G1 GC 알고리즘](https://steady-coding.tistory.com/590) 183 | [GC-static -1](https://8iggy.tistory.com/230) 184 | [GC-static -2](https://8iggy.tistory.com/229) 185 | -------------------------------------------------------------------------------- /Java/Generic.md: -------------------------------------------------------------------------------- 1 | # Generic 2 | 3 | ### 1. Generic 이란 4 | * 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주고 형변환의 번거로움을 줄여주는 기능을 하는 것입니다. 5 | 6 | #### Q) Generic에는 어떤 타입이 가능한가? 7 | - 제너릭은 레퍼런스 타입만 사용이 가능합니다. 따라서 기본형 타입을 제너릭에 사용하려면 Wrapper 클래스를 사용해야합니다. 8 | 9 | #### Q) Generic의 장점에는 무엇이 있는가? 10 | - 타입의 안정성을 제공해주고, 타입 체크와 형변환을 생략할 수 있으므로 코드가 간결해진다. 11 | - 부모 타입을 미리 정할 수 있고, 다형성으로 유연한 설계가 가능하기 떄문에 재사용성도 높아진다. 12 | 13 | #### Q) 제너릭 타입이 컴파일 시에 제거되는 과정을 말해주세요. 14 | 1. 제너릭 타입의 경계를 제거합니다. `` 이때 T는 Fruit로 치환됩니다. 만약 `` 였다면 Object로 치환됩니다. 15 | 2. 타입 제거 후 타입이 일치하지 않는 곳은 형변환을 추가해줍니다. 16 | ```java 17 | List list = new ArrayList(); 18 | 19 | Fruit get(int i) { 20 | //return list.get(i); Object, Fruit 일치 X 21 | return (Fruit) list.get(i); 22 | } 23 | ``` 24 | - 제너릭 타입을 컴파일 당시에 제거하는 이유는 JDK 1.5에 제너릭이 도입되었는데, 그 이전 코드와의 호환성을 위해 이러한 과정을 거치는 것이다. 25 | 26 | #### Q) 제한된 제너릭(Bounded Generic)의 장점에 대해서 설명해주세요. 27 | - 기존의 제너릭은 타입을 하나 밖에 선언하지 못하여 유연성이 좋지 않다는 문제가 있었습니다. 하지만 제한된 제너릭을 사용하면 유연성있게 특정 타입의 자손 혹은 구현체들에 대해 타입 지정을 할 수 있게 됩니다. 28 | 29 | #### Q) `List` 와 `List` 의 차이에 대해서 설명해주세요. 30 | - ``List`` 는 Object 타입만 들어 올 수 있고, ``List``은 다양한 타입이 들어오는 게 가능합니다. 31 | - 와일드카드의 큰 장점은 형변환에 있다. 하지만, 컴파일 에러가 아닌 경고 메시지를 반환하므로 주의해서 사용해야 한다. 32 | 33 | #### Q) Integer 타입이 들어온다면 ``, `` 둘 중 어디에 일치하는가 34 | - `` 에 일치합니다. 35 | 36 | #### Q) 코드에서 `` 와 `` 가 달려있는 것을 보고 어떻게 해석할 것인가. 37 | - `` 가 달려있다는 것은 정말 엄격하게 해당 타입만 사용해야 하는 것으로 판단하여, 형변환 이나 다른 타입을 사용하지 않도록 주의 할 것이고, ``의 경우에는 여러가지 타입을 상황에 맞게 적절히 생성해서 사용하라는 것으로 해석 할 것 같다. -------------------------------------------------------------------------------- /Java/JDK8.MD: -------------------------------------------------------------------------------- 1 | # JDK 8 2 | 3 | 4 | ### Q) 스트림 API에 대해 설명해주세요 5 | 6 | 람다식를 이용한 기술 중에 하나로 컬렉션, 배열 등을 조작 및 가공, 변환하여 원하는 값으로 반환해주는 API 7 | 8 | ### Q) 스트림이 나오게된 이유는? 9 | 10 | - 자바를 이용해 함수형프로그래밍을 할수있게끔 지원해주기위해 11 | - 데이터 조작작업을 병렬로 구성하여 실행할수있게되어 **데이터 변환 수행 방식**에 집중하기보다는 **수행되는 데이터변환**에 중점을 두어 간결하고 가독성이 좋은 코드를 작성할수있게끔하기위해 12 | 13 | ### Q) 일반적인 for-loop 보다 스트림의 for-each가 느린이유 14 | 15 | - 반복문 내부에 특정조건을 만족하면 종료조건이있는경우 기존의 for-loop는 조건을 만족하면 바로 종료하지만 stream의 forEach는 종료조건이 만족되도 모두 조건을 확인한다. 16 | 17 | ### Q) 함수형 인터페이스에대해 설명해주세요 18 | 19 | - 추상메서드를 하나만 가지고있는 인터페이스 20 | - 함수형 인터페이스여야만 람다표현식에 사용할수있다. 21 | 22 | ### Q) java에서 제공하는 함수형 인터페이스에대해 설명해주세요 23 | 24 | - `Supplier` 25 | - 매개변수 없이 반환값만을 가진다. 26 | - `Consumer` 27 | - 매개변수를 받고 반환값은 가지지않는다. 28 | - `Predicate` 29 | - 객체 T를 받고 30 | - `Function` 31 | - 객체 T를 매개변수로 받고 R로 반환한다. 32 | 33 | ### Q) Optional 에대해 설명해주세요 34 | 35 | - null 을 처리하기위한 좋은방법을 제공하는 API로 null을 반환할수있는 경우 Optional을 사용해서 NullPointException을 효율적으로 처리할수있다. 36 | -------------------------------------------------------------------------------- /Java/JVM.md: -------------------------------------------------------------------------------- 1 | # JVM 2 | 3 | 자바 프로그램은 OS가 바로 해석할수있는 상태의 기계어가 아닌 바이트코드상태인데 이 바이트코드를 해석하고 실행할수있게 해주는 자바 가상머신입니다. 4 | 5 | ### JVM 메모리 구조에 대해 간단히 설명해주세요 6 | 7 | - 클래스로더에서 .class파일을 읽어 .class파일의 데이터를 메소드영역에 저장하고 로드가 끝나면 해당 클래스타입의 class객체를 생성해 heap 영역에 저장한다. 8 | 9 | - 메모리(런타임 데이터)영역은 JVM이 로드하고 실행할때마다 바이트코드, 객체, 변수등을 저장하기위한 메모리 공간들을 의미한다. 10 | 11 | - 스택: 스레드마다 스택이라는걸 만든다. 해당 스레드가 수행하는 메서드호출, 로컬변수 등의 정보를 포함하여저장한다. **스택에 저장된 데이터는 해당스레드에서만 사용가능해서 thread-safe하다**. 12 | 13 | - PC : 스레드마다 스레드내 현재 실행할 스택프레임을 가리키는 포인터가 생성된다. 14 | 15 | - 네이티브 메소드스택 : Native 메소드를 사용할떄 사용하는 별도의 스택 16 | 17 | - 힙: JVM시작시 생성되는영역 , 객체를 저장하는영역, **공유자원**이다. 18 | 19 | - 메소드: JVM시작시 생성되는영역,정적변수를 포함한 클래스 수준의정보(클래스이름, 부모클래스이름, 메소드,변수 등등)저장, 공유 자원이며, static zone/ non-static zone 으로 나뉜다. 20 | 21 | > ### 바이트코드와 바이너리코드의 차이점에대해 설명해주세요 22 | 23 | - 바이트 코드 : CPU가 아닌 가상머신에서 이해할수있는 코드를위한 이진표현법, 어떤 플랫폼에 종속되지않고 실행할수있는 기계어코드 24 | 25 | - 바이너리 코드 : CPU가 이해할수있는언어로, 0과 1로 구성된 이진코드를 의미한다 26 | 27 | - 바이트코드는 **가상머신에서 이해할수있는 코드를위한 표현법**이고, 바이너리코드는 **CPU가 이해할수있는언어로 구성된 이진코드**를 의미한다. 28 | 29 | ### JIT 컴파일러는 왜 생겼는가? 항상 사용하면 좋은건지? 30 | - 바이트코드를 한줄씩 실행하는것이 인터프리터인데 반복되는 부분이 있는경우 JIT컴파일러가 바이트코드의 패턴을 내부적으로 감지해 native 코드로 변환하거나 컴파일후 캐싱하는등 인터프리터의 효율을 높이기위해 등장했다. 31 | 32 | - 간단한 바이트코드라면 JIT컴파일러도 패턴을 감지하거나 내부적인 알고리즘이 있기때문에 비용이 있을것이고 인터프리터만 사용하는것이 좋을경우도 존재한다. 33 | 34 | ### JVM 스택영역와 힙영역의 차이점 35 | 36 | - 스택은 스레드별로 생기는공간으로 스레드간 공유가 되지않지만 heap은 스레드끼리 공유할수있는 공유자원이다. 37 | 38 | - 스택은 해당 스택에서 호출한 메서드, 지역변수들의 정보를 저장하지만 heap은 객체를 저장한다. 39 | 40 | 41 | ### A a = new A(); 생성시 42 | test라는 메서드에서 실행한다고 가정했을때 43 | a라는 변수는 stack 영역에 저장되고 A객체가 heap에 생성되고 a변수가 heap에 있는 A객체를 가리키게된다. 44 | 45 | ### method 영역에는 어떤게 저장되나요? 46 | 클래스로더에서 .class파일을읽고 .class파일에 대한 메타정보를 저장하고 static변수들이 저장된다. 47 | 48 | ### String = "a", new String("a") 는 각각 어디에 생성되나요? 49 | new String("a")로 생성하면 heap영역에 생길꺼고 , String = "a"로 생성하면 자바8이전이라면 method 영역에 있는 상수풀, 자바8이후이면 heap영역에 있는 상수풀에 저장됩니다. 50 | -------------------------------------------------------------------------------- /Java/Modifier.md: -------------------------------------------------------------------------------- 1 | # Modifier 2 | - 제어자란(modifier) ? 3 | - 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여합니다. 4 | - 접근제어자 : public, protected, default, private 5 | - 그 외 제어자 : static, final, abstract, native, transient, synchronized, volatile .. 6 | - 하나의 대상에 여러 개의 제어자를 조합해서 사용할 수 있으나, 접근제어자는 단 하나만 사용할 수 있습니다. 7 | 8 | - 1. static : 메모리를 공유하여 사용 9 | - '클래스의' 또는 '공통적인' 의미를 가지고 있다. 10 | - static이 붙은 멤버변수와 메서드, 초기화 블럭은 인스턴스를 생성하지 않고도 사용할 수 있다. 11 | - static 멤버변수 12 | - 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다. 13 | - 클래스변수는 인스턴스를 생성하지 않고도 사용가능하다. 14 | - 클래스가 메모리에 로드될 때 생성된다. 15 | 16 | - static 메서드 17 | - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다. 18 | - static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다. 19 | 20 | - 2. final : 해당 변수는 값이 저장되면 최종적인 값이 되므로, 수정이 불가능 21 | - '마지막의' 또는 '변경될 수 없는' 의미를 가지고 있다. 22 | - final 클래스 23 | - 변경 될 수 없는 클래스, 확장될 수 없는 클래스가 된다. 24 | - 다른 클래스의 조상이 될 수 없다. 25 | - final 메서드 26 | - 변경 될 수 없는 메서드, 오버라이딩을 통해 재정의 될 수 없다. 27 | - final 멤버변수, final 지역 변수 28 | - 변경 할 수 없는 상수가 된다. 29 | - final이 붙은 변수는 상수이므로 보통은 선언과 초기화를 동시에 하지만, 인스턴스변수의 경우 생성자에서 초기화 할 수 있다. 30 | 31 | - Static Final 32 | - 두개를 합쳐서 생각해보면 고정되어 최종적으로 사용된다고 보면된다. 33 | - 즉, 클래스 자체에 존재하는 단 하나의 상수이다.(클래스자체로 존재하여 접근가능하고 불변하다) 34 | - 따라서 클래스의 선언과 동시에 반드시 초기화가 필요한 클래스 상수이다. 35 | 36 | ### Q) 메소드 parameter 에 final 에 붙이는 경우를 어떻게 생각하시는지 설명해주세요. 37 | - 매개변수가 변경 불가능한 상황을 의미합니다. 38 | - 매개변수에 final 을 붙이면, 넘어온 매개변수를 변경하지 못하도록 강제하므로 매개변수를 변경하지 말아야 하는 경우, 이를 명시하고 싶을 때 사용하면 적합할 것이라고 판단합니다. 39 | 40 | - 아래 코드는 컴파일 에러 (The final local variable website cannot be assigned. It must be blank and not using a compound assignment ) 가 발생합니다. 41 | - 이와 같이 넘어온 매개변수의 변경 방지를 강제할 때 사용한다면 유용할 것입니다. 42 | 43 | ```java 44 | static class FinalParameterTest{ 45 | 46 | public void show(final String website){ 47 | website = "java.com"; // 변경하려고 시도라면 48 | System.out.println("website = " + website); 49 | } 50 | } 51 | 52 | public static void main(String args[]){ 53 | //creating object of FinalParameterTest Class 54 | FinalParameterTest obj = new FinalParameterTest(); 55 | obj.show("w3spoint.com"); 56 | } 57 | ``` 58 | 59 | ![image](https://user-images.githubusercontent.com/76711238/236809825-4ba53339-6f14-4d5c-9821-ded4140f76e2.png) 60 | 61 | 62 | #### 사진 & 내용 출처 63 | https://guccin.tistory.com/155 64 | 65 | https://stackoverflow.com/questions/2236599/final-keyword-in-method-parameters 66 | -------------------------------------------------------------------------------- /Java/OOP.md: -------------------------------------------------------------------------------- 1 | # 객체지향언어 2 | 3 | ### 1. 객체지향의 특징이 무엇이 있나요? 4 | * 객체지향이란, **함수에 객체를 사용하여 메시지를 전달하는 것이고, 객체를 자율적인 존재로 바라보는 것**입니다. 5 | * 객체지향의 특징에는 크게 4가지가 있습니다. **캡슐화**, **상속**, **다형성**, **추상화** 입니다. 6 | 7 | 1. **캡슐화** 8 | - **객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다.** 9 | 객체는 자율적인 존재로서 동작해야하고 외부에서 직접 접근하여 객체의 상태를 변경하려고 해서는 안됩니다. 이를 방지하기 위함입니다. 10 | 11 | 2. **상속** 12 | - **기존의 클래스를 재활용하여 새로운 클래스를 작성하는 것**입니다. 13 | 상속으로 인해 속성과 행위들을 간편하게 재사용하거나 반복적인 코드를 최소화 할 수 있고, 다형성을 적용할 수도 있습니다. 14 | - 상속은 크게 2가지로 구분됩니다. 15 | 1. **서브타이핑** 16 | - 서브타이핑의 경우 서브 클래스가 슈퍼 클래스를 대체할 수 없는 경우를 말합니다. 설계를 유연하게 하기 위해 사용합니다. 이를 **인터페이스 상속** 이라고 합니다. 17 | 2. **서브클래싱** 18 | - 서브클래싱의 경우 서브 클래스가 슈퍼 클래스를 대체할 수 있는 경우를 말합니다. 주로 코드의 중복 제거와 재사용이 목적입니다. 이를 **구현 상속** 이라고 합니다. 19 | 20 | 3. **다형성** 21 | - **어떤 객체의 속성이나 기능이 상황에 따라 여러가지 형태를 가질 수 있는 성질**입니다. 22 | 실제 프로그래밍에 적용한다면, 부모의 참조타입으로 자식의 인스턴스를 다루는 것을 의미합니다. 23 | - 이를 활용하여, 메시지 송신자의 입장에서 수신자의 분명한 구성 클래스를 알지 못하더라도 메시지를 유연하게 전달 할 수 있습니다. 24 | 25 | 4. **추상화** 26 | - **불필요한 세부 사항들은 제거하고 가장 본질적이고 공통적인 부분만을 추출하여 표현하는 것**입니다. 프로그래밍적 관점에서는 객체의 공통적인 속성과 행위를 추출하는 것입니다. 27 | 28 | ### 2. SOLID 원칙 29 | * SOLID 원칙은 객체 지향 설계의 다섯 가지 기본 원칙을 말합니다. SRP, OCP, LSP, ISP, DIP로 구성되어 있습니다. 30 | 31 | 1. **SRP(Single Responsibility Principle, 단일책임원칙)** 32 | - **한 클래스는 하나의 책임만 가져야 한다는 원칙** 33 | - 이 원칙은 설계 당시에 제대로 지켜져있는지 알기 쉽지 않고, 리팩토링을 하는 과정에서 해당 클래스에 많은 변경사항이 발생된다면 단일 책임 원칙에 위배 된 것이므로 올바른 설계가 되었는지 다시 생각해봐야 합니다. 34 | 35 | 2. **OCP(Open Closed Principle, 개방폐쇄원칙)** 36 | - **소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.** 37 | - 실제 내부 구성 코드를 변경해서 소프트웨어를 확장하는 것이 아닌, 다형성을 이용해서 알고리즘 군을 형성하고 외부에서 구성 클래스만 추가하여 유연하게 수정하는 방식입니다. 38 | - 이때, 확장과 변경의 기준은 객체 자신의 기준입니다. 객체 외부에서는 확장을 위해 변경이 발생할 수 있습니다. 39 | 40 | 3. **LSP(Liskov Substitution Principle, 리스코프 치환 원칙)** 41 | - 프로그램 **객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다**. 42 | - 다른 말로 **슈퍼타입을 서브 타입이 대체 가능한 것**을 의미합니다. 43 | 44 | 4. **ISP(Interface Segregation Principle, 인터페이스 분리 원칙)** 45 | - **특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.** 46 | - 역할을 여러 개로 나눈다면, 다형성으로 인해 유연한 설계가 가능합니다. 47 | 48 | 5. **DIP(Dependency Inversion Principle, 의존관게 역전 원칙)** 49 | - **추상화에 의존하고, 구체화에 의존하면 안된다.** 50 | - 이를 이용해, 메시지를 유연하게 전송할 수 있고, 수신자의 입장에서 해당 객체를 유연하게 받기 위해 사용하는 의존성 주입이 이 원칙을 따르는 방법 중에 하나입니다. 51 | 52 | ### 2. 개발을 할 때 객체지향적으로 프로그래밍을 하는가. 만약에 했다면 객체지향의 어떤 특징을 이용하여 적용을 하였는가. 53 | - 실제 프로젝트에서 인프라 관련해서 수정이 발생하는 부분이 있었고, 이를 객체지향의 다형성과 OCP, ISP, DIP를 이용하여 인프라에 따라 다른 구성 클래스가 적용될 수 있도록 인터페이스를 설계하여 구현한 적이 있습니다. 이를 이용해 실제 코드를 건드리지 않고 유연하게 구성 클래스를 교체하여 프로젝트의 코드를 유연하게 작성 할 수 있었습니다. 54 | 55 | #### Q) 개방 폐쇄 원칙과 다형성의 관계에 대해서 설명해주세요. 56 | - 개방 폐쇄 원칙은 객체 내부의 코드는 변경하지 않고, 확장이 가능하도록 하는 것입니다. 이를 가능하게 하기 위해서 다형성이 필요합니다. 주로 개방 폐쇄 원칙은 DIP와 많이 따라다니게 되는데 의존 주입 방식이 OCP를 지키면서 DIP도 지키는 방식이기 때문입니다. 의존 주입할 구성 클래스에 대상을 추상 클래스로 받도록 하고, 외부에서 메시지를 송신할 때 구성 클래스를 전송함으로써 객체 내부에서는 자율적으로 구성 클래스에 맞게 행동 할 수 있습니다. 57 | - 즉, 객체의 속성이나 기능이 상황에 따라 여러가지 형태를 가질 수 있다는 다형성의 특징을 사용한 것으로 볼 수 있습니다. 58 | 59 | ### 3. 추상클래스와 인터페이스의 공통점과 차이점에 대해서 설명해주세요. 60 | **[공통점]** 61 | - 추상클래스와 인터페이스 모두 추상 메서드를 선언하고 이를 상속 혹은 구현을 해야만 동작이 가능하고, 생성자를 통해 각 추상클래스와 인터페이스는 생성 할 수 없다는 공통점을 가지고 있습니다. 62 | 63 | **[차이점]** 64 | - 자바에서 클래스는 단일 상속밖에 안되기 때문에, 추상 클래스는 단, 하나만 사용할 수 있으며 인터페이스는 다중 구현이 가능하기 때문에 여러 개의 인터페이스를 구현이 가능합니다. 65 | - 추상 클래스는 추상 메서드를 제외하고 메서드나 변수의 선언이 가능하기 때문에 변수 혹은 메서드의 재사용성이 높아진다는 장점이 있습니다. 66 | - JDK 1.8 이후로 인터페이스에 default 키워드 및 상수를 추가할 수 있도록 변경되었습니다. 67 | 이에 따라, 인터페이스도 메서드를 공통된 메서드가 겹칠 수 있는 두 가지 상황이 있습니다. 68 | 1. 인터페이스 간의 default 메서드가 중복되어 충돌 됐을 경우 69 | - 오버라이딩을 통해서 해결 할 수 있습니다. 70 | 2. 조상메서드와 default 메서드가 충돌 됐을 경우 71 | - default 메서드는 무시하고 조상 메서드를 상속합니다. 72 | 73 | ### 4. 캡슐화의 특징인 정보은닉과 연계해서 프로젝트 도중 캡슐화의 장점을 겪은 경험이 있는가 74 | - 프로젝트간 객체에게 메시지를 전달하는 과정에서 어떠한 행위를 수정하지 않아도 되도록 하고, 이 과정에서 메시지 수신자 내부에서 요청을 받은 행위에 대한 수정이 있더라도 송신한 객체는 그 코드 부분을 건드리지 않고도 기능을 확장 할 수 있었습니다. 75 | 76 | #### Q) 인터페이스의 default 메서드가 나오게 된 계기에 대해서 설명해주세요. 77 | - 인터페이스의 가장 큰 단점은 새로운 추상 클래스가 추가된다면 인터페이스를 구현한 구성클래스들이 해당 공통 로직을 전부다 구현해줘야 한다는 단점이 있었습니다. 78 | - 이러한 불편함을 개선하기 위해서 default 메서드를 추가함으로써 새로운 기능이 추가되더라도 구성클래스들이 해당 기능을 구현하지 않아도 동작이 가능해졌습니다. 79 | 80 | #### Q) 인터페이스에서 default 메서드를 사용하게 되면 추상 클래스와 크게 다르지 않을 것 같은데 차이점이 있을까요? 81 | - 추상클래스와 인터페이스의 목적이 다릅니다. 추상 클래스는 코드의 중복을 제거하고 부모의 기능을 재사용을 하기 위해 사용하며, 단일 상속밖에 안된다는 단점이 있고, 인터페이스는 코드의 유연한 설계를 위해 사용하는 것이고, 다중 구현이 가능합니다. 따라서, 상황에 맞게 적절하게 사용 할 필요가 있습니다. 82 | 83 | ### 5. 스프링의 AOP에 대해서 설명해주세요. 84 | - 애플리케이션은 크게 핵심 기능과 부가 기능으로 나눌 수 있습니다. 여기서 AOP(Aspect-Oriented-Programming, 관점 지향 프로그래밍)는 부가 기능을 추가하기 위해 도입된 개념입니다. **프록시를 통해서 구현이 가능하며 주로 횡단 관심사 관점으로 달리 보는 것**입니다. 85 | - AOP를 적용하기 위해서 필요한 것은 크게 2가지입니다. 첫 번째는 **Point Cut**이며, 두 번째는 **Advice**입니다. 86 | 1. **Point Cut** : AOP의 적용 범위를 설정하기 위해 사용합니다. 즉, 필터가 목적입니다. 87 | 2. **Advice** : 프록시 패턴 혹은 데코레이터 패턴을 적용하는 주요 로직에 해당하는 부분입니다. 88 | - 그리고 위의 두 가지를 합친 것을 **Advisor**라고 하며, 스프링의 후처리기는 Advisor를 찾아 적용하는 방식입니다. 89 | 90 | #### Q) AOP는 객체지향의 특징에서 어떤 부분과 연관지을 수 있을까요? 91 | - AOP는 기본적으로 프록시를 사용합니다. 프록시란 주 기능을 수행하기 위해 부가적인 기능을 수행할 수 있도록 도와주는 것인데, 이 과정에서 **구성 클래스의 로직을 건드리지 않고 외부에서 어떤 코드를 추가하여 기능을 확장 할 수 있으므로, 개방폐쇄원칙과 가장 큰 연관**이 있다고 생각합니다. 92 | - 추가적으로 해당 부가기능을 수행하는 프록시는 **어떠한 부가기능을 추가하기 위해 해당 기능만을 담당하기 때문에 단일 책임 원칙과도 큰 연관**이 있다고 생각합니다. 93 | 94 | #### Q) DIP에 대한 예시 하나만 설명해주세요. 95 | - DIP를 활용하면 주된 방식 중 하나인 DI(Dependency Injection, 의존 주입)가 있습니다. 96 | - 이를 이용해 구성 클래스가 유연하게 교체가 가능하도록 설계가 가능합니다. 97 | 98 | ### 6. 객체지향적으로 개발을 하기 위해 제일 고려해야 하는 것은 무엇인가요? 99 | - 사용자의 요구사항에 대해서 만족시킬 수 있도록 도메인적 관점에서 바라보고, 설계 시 그 행위에 초점을 두어야 한다고 생각합니다. 100 | - 행위에 초점을 두었을 때, 해당 객체들이 메시지를 송신하는데에 있어서 각 객체가 서로 어떻게 연관이 되어야 하는지 갈피가 잡히고, 여기서 행동을 하는데에 필요한 것을 상태로 추가하여 설계해야 합니다. 101 | 102 | ### 7. 업캐스팅과 다운캐스팅에 대해서 설명해주세요. 103 | - 부모의 참조변수를 가지고 자손 타입의 인스턴스 객체를 참조하는 경우에 **자손 타입의 인스턴스에서 부모 타입의 인스턴스로 형변환 하는 것**을 **업캐스팅**이라고 하며, **부모 타입의 인스턴스에서 자손 타입의 인스턴스로 형 변환 하는 것**을 **다운 캐스팅**이라고 합니다. 104 | 105 | #### Q) 부모와 자식이 있을 때, 자식 클래스를 생성하는 경우 어떤 클래스가 먼저 생성될까요? 106 | - 자식 클래스의 생성자에는 **기본적으로 부모 클래스의 생성자를 생성자의 최상위에 호출**을 해주어야 하기 때문에, **부모 클래스가 먼저 생성되고 그 이후에 자식 클래스가 생성**됩니다. 107 | -------------------------------------------------------------------------------- /Java/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Java/Synchronization.md: -------------------------------------------------------------------------------- 1 | # Synchronization 2 | - **동기화** 란, 프로세스(스레드)가 수행되는 시점을 조절하여 서로가 알고 있는 정보가 일치하는 것인데, 쉽게 말해 프로세스 간 데이터가 일치하도록 하는 것을 의미합니다. 3 | 4 | - 동기화 메커니즘인 **상호배제**는 프로세스들이 필요로 하는 자원에 대해 배타적인 통제권을 요구하는 것입니다. 즉, 하나의 프로세스가 공유자원을 사용할 때 다른 프로세스가 동일한 공유자원에 접근할 수 없도록 통제하는 것을 뜻합니다. 5 | 6 | - Monitor은 임계 구역을 지켜내기 위한 방법인 상호 배제를 프로그램으로 구현한 것입니다. 순차적으로 사용할 수 있는 공유 자원 혹은 공유 자원 그룹을 할당하는 데 사용됩니다. 모니터는 이진 세마포어만 가능합니다. 모니터를 통해 프로세스가 자원에 접근하는 방식을 이미지로 보면 아래와 같습니다. 7 | ![image](https://user-images.githubusercontent.com/76711238/236782612-46cbe66b-a17c-4b70-8af8-13f16dd01f50.png) 8 | - 공유 자원에 점유 중인 프로세스(스레드)는 Lock 을 가지고 있습니다. 9 | - 공유 자원을 점유 중인 프로세스(스레드)가 있는 상황에서 다른 프로세스(스레드)가 공유 자원에 접근하려고 하면 외부 모니터 준비 큐에서 진입을 wait 합니다. 10 | - Monitor 는 Semaphore 처럼 signal 연산을 보내는 것이 아니라 조건 변수를 사용하여 특정 조건에 대해 대기 큐에 signal 을 보내 작업을 시작시킵니다. 11 | 12 | - Java 에서는 이러한 `Monitor` 을 통해 객체에 Lock 을 걸어 상호배제를 할 수 있습니다. 이러한 monitor를 가질 수 있는 것은 `synchronized` 키워드 내에서 가능합니다. 13 | - Monitor는 여러 스레드가 객체로 동시에 객체로 접근하는 것을 막습니다. 여기서 모든 객체라는 사실이 중요한 이유는 heap 영역에 있는 객체는 모든 스레드에서 공유 가능하기 때문입니다. 14 | - 스레드가 monitor를 가지면, monitor를 가지는 객체에 lock을 걸 수 있습니다. 그렇게 되면 다른 thread들이 해당 객체에 접근할 수가 없습니다. 15 | - 즉 흔히 스레드가 공유객체의 lock을 얻는다는 것이 monitor (혹은 monitor lock)을 얻는 것을 말합니다 16 | - Monitor에 접근한 스레드는 Entry Set에 대기합니다. Monitor에 접근 가능한 스레드는 단 한 개뿐이기 때문입니다. 17 | ![image](https://user-images.githubusercontent.com/76711238/236784824-7009f0b2-ad24-496c-b2d1-96161a28c6bb.png) 18 | 19 |
20 | ※ intrinsic lock (고유 락) 21 | 22 | - 자바의 모든 객체는 lock 을 가지고 있습니다. 23 | - 이를 고유 락 (intrinsic lock) 또는 모니터 락 (monitor lock) 이라고 부릅니다. 24 | - synchronized 는 고유 락을 사용하는데, synchronized 메서드가 호출되면 해당 스레드는 고유 락을 획득하고 메서드가 종료되면 락을 해제합니다. 25 | 26 |
27 | 28 | ### Q) Thread-local 에 대해서 설명해주세요. 29 | - 오직 한 쓰레드에 의해서 읽고 쓰여질 수 있는 변수입니다. 두 쓰레드가 같은 코드를 실행하고 이 코드가 하나의ThreadLocal 변수를 참조 하더라도 서로의 ThreadLocal 변수를 볼 수 없습니다. 30 | - 즉, ThreadLocal 변수를 선언하면 멀티쓰레드 환경에서 각 스레드마다 독립적인 변수를 가지고 접근 할 수 있습니다. 31 | - 활용 1) Thread-local 클래스를 활용하면 스레드 단위로 로컬 변수를 사용할 수 있기 때문에 마치 전역변수처럼 여러 메서드에서 활용할 수 있습니다. (한 쓰레드에서 실행되는 코드가 동일한 객체를 사용할 수 있도록 해주기 때문에 관련된 코드에서 파라미터를 사용하지 않고 객체를 각자가 가져다 쓸때 사용 됩니다.) 32 | - 활용 2) 클라이언트 요청에 대해서 각각의 스레드에서 처리할 때나, 스레드 독립적으로 처리해야 하는 데이터와 같이 인증 관련 처리에서도 활용될 수 있습니다. 33 | - 활용 3) 사용자 인증 정보 Spring Security 에서 사용자마다 다른 인증 정보/Session정보를 사용해야 할 때 사용됩니다. 34 | 35 | ### Q-1) 멀티쓰레드 환경에서 Thread-local 을 사용할 때 유의할 점에 대해 설명해주세요. 36 | - 쓰레드 로컬은 **메모리 누수의 주범**이 됨으로 주의해서 사용해야 합니다. 37 | - 또한 스레드 로컬은 스레드 풀(thread pool)을 사용하는 환경에서는 주의해야 합니다. 스레드가 재활용될 수 있고 **재사용 되는 쓰레드가 올바르지 않은 데이터를 참조할 수도 있기 때문**에, 사용이 끝났다면 스레드 로컬을 비워주는 과정이 필수적입니다. 38 | - 이와 같이 스레드 풀을 통해서 스레드가 재사용되기 때문에 의도하지 않은 결과가 발생할 수 있습니다. 이러한 문제를 방지하려면 사용이 끝난 스레드 로컬 정보는 제거될 수 있도록 `remove` 메서드를 마지막에 명시적으로 호출하면 됩니다. 39 | 40 | ### Q) synchronized 를 사용할 시 sychronized method, sychronized block, static sychronized method, static synchonized block 의 4가지 쓰임새 경우에 대해 설명해주세요. 41 | 42 | - 1. synchronized method 43 | - 클래스 **인스턴스** 에 lock을 겁니다. 44 | - 동일한 인스턴스 내 synchronized 키워드가 적용된 메서드끼리 lock을 공유합니다. 45 | 46 | - 2. static synchronized method 47 | - 인스턴스가 아닌 **클래스 단위** 로 lock을 겁니다. 48 | - 다른 인스턴스더라도 static 메서드에 synchronized가 붙은 경우 lock을 공유할 수 있습니다. 49 | - static synchronized와 synchronized가 혼용되어있을 때 각자의 lock으로 관리 50 | 51 | - 3. synchronized block 52 | - **인스턴스의 block 단위** 로 lock을 걸고 lock 객체를 지정해야 합니다. 53 | - this를 명시하면 synchronized method와 동일하게 동작하면서 synchronized method와 lock을 공유합니다. 54 | - 특정 객체를 명시하면 해당 객체에만 특정 lock을 걸면서 해당 객체에 lock을 거는 block끼리만 lock을 공유합니다. 55 | - .class 형식 명시하면 해당 클래스에만 특정 lock을 걸면서 해당 클래스에 lock을 거는 block끼리만 lock을 공유합니다. 56 | 57 | - 4. static synchronized block 58 | - 인스턴스가 아닌 **클래스 단위** 로 lock을 겁니다. 59 | - block의 인자로 정적 인스턴스나 클래스만 사용 60 | - static 메서드 안에도 synchronized block을 사용할 수 있는데 이때는 this와 같이 현재 객체를 가르키는 표현은 사용할 수 없습니다. 61 | - static synchronized method 방식과의 차이는 lock 객체를 지정하고 block 범위를 한정 지을 수 있다는 점입니다. 62 | 63 | ### Q-1) synchronized 사용 시 데드락이 발생하는 상황을 설명해주세요. 64 | - **Deadlock** : 상호 배타적인 접근을 동시 수행하려 할 때 발생하는 현상입니다. 65 | - **synchronized 사용 시 Deadlock 발생 경우** : Thread 1 번이 Transaction 수행 중 A 객체에 대한 monitor Lock 을 잡은 상태에서 B 객체에 대해 monitor Lock 을 잡기 위해 접근하는 상황에서 Thread 2 번이 B 객체에 대해 monitor Lock 을 획득 하 고 연산을 수행하는 도중에 A 객체의 monitor Lock 을 잡기 위해 대기 하는 상황이 발생합니다. 이렇게 서로가 서로의 Lock 을 먼저 해제하기만을 기다리고 있는 상황이 바로 Deadlock 현상입니다. 66 | 67 | - ![image](https://user-images.githubusercontent.com/76711238/236788130-67b9f113-2268-442f-bbf5-6b9f924fa231.png) 68 | - Thread 가 Deadlock 상황에 빠지게 되면 서로 다른 쪽의 monitor Lock 을 획득하기 위해 무한 대기합니다. 이러한 Transaction 이 빈번하게 수행 된다면 얼마 지나지 않아 가용 Thread 가 전부 소진되어 서비스 장애가 일어날 것입니다. 69 | 70 | - **해결방법** : `Synchronized` 를 사용해야만 하는 환경에서 Deadlock 을 회피하기 위해서는 `Synchronized` 로 동기화 된 자원에 대해 어떤 Application 이든지 **항상 같은 순서로 참조하게 하면 되는 것**입니다. 위의 상황에서 B, C Method 를 수행하는 모든 Application 이 B Method 수행 후에 C Method 를 수행하도록 짜여져 있다면 Deadlock은 발생하지 않을 것입니다. 71 | 72 | ### Q) volatile 키워드에 대해 설명해주세요. 73 | - 동시성 프로그래밍에서 발생할 수 있는 문제 중 하나인 가시성 문제를 해결하기 위해 사용되는 키워드입니다. 가시성 문제는 여러 개의 스레드가 사용됨에 따라, CPU Cache Memory와 RAM의 데이터가 서로 일치하지 않아 생기는 문제를 의미합니다. volatile 키워드를 붙인 공유 자원은 RAM에 직접 읽고 쓰는 작업을 수행할 수 있도록 해줍니다. 74 | 75 | - 동시성 프로그래밍에서 가시성 문제로 인한 공유 자원 접근 시 문제 상황이 발생할 수 있습니다. 가시성 문제란, 여러 개의 스레드가 사용됨에 따라, CPU Cache Memory와 RAM의 데이터가 서로 일치하지 않아 생기는 문제를 의미합니다. 76 | 77 |
78 | CPU와 RAM의 관계도 79 | 80 | ![image](https://user-images.githubusercontent.com/76711238/236790675-af22c4e1-4897-4b81-8a44-301c13a4e4c4.png) 81 | 82 | - CPU가 어떤 작업을 처리하기 위해 데이터가 필요할 때, CPU는 RAM의 일부분을 고속의 저장 장치인 CPU Cache Memory로 읽어들입니다. 83 | - 이 읽어들인 데이터로 명령을 수행하고, RAM에 저장하기 위해서는 데이터를 CPU Cache Memory에 쓴 다음 RAM에 쓰기 작업을 수행합니다. 84 | - 그러나 CPU가 캐시에 쓰기 작업을 수행했다고 해서 바로 RAM으로 쓰기 작업을 수행하지 않습니다. 85 | - 반대로 읽기 작업도 해당 데이터가 RAM에서 변경이 되었다고 해도, 언제 CPU Cache Memory가 아닌 RAM에서 데이터를 읽어 들여서 CPU Cache Memory를 업데이트할 지 보장하지 않습니다. 86 | - 동시성 프로그래밍에서는 CPU와 RAM의 중간에 위치하는 CPU Cache Memory와 병렬성이라는 특징때문에 다수의 스레드가 공유 자원에 접근할 때 두 가지 문제가 발생할 수 있습니다. 87 | 88 |
89 | 90 | - 이를 해결하기 위해서는 가시성이 보장되어야 하는 변수를 CPU Cache Memory가 아니라 RAM에서 바로 읽도록 보장해야 합니다. 이때 변수에 valatile 키워드를 붙임으로써 변수를 CPU Cache Memory가 아니라 RAM에서 바로 읽도록 보장이 가능하며, 결국 가시성을 보장할 수 있습니다. 91 | 92 | - **다만 가시성이 보장된다고 동시성이 보장되는 것은 아닙니다.** 93 | - volatile 키워드는 어디까지나 volatile 변수를 메인 메모리로부터 읽을 수 있게 해 주는 것이 전부이고, 다른 스레드에 의해 이 값이 언제든 바뀔 수 있다. 즉, 가시성이란 공유 데이터를 읽는 경우의 동시성만 보장하는 것이라 생각하면 됩니다. 94 | 95 | ### Q-1) lock을 사용했을 시와 volatile을 사용할 시에, volatile 단점에 대해서 설명해주세요. 96 |
97 | 가시성 문제과 원자성 문제 98 | 99 | ### 가시성 문제 100 | - CPU - Cache - Memory 관계 상의 개념 101 | - 여러 개의 스레드가 사용됨에 따라, CPU Cache Memory와 RAM의 데이터가 서로 일치하지 않아 생기는 문제를 의미합니다. 102 | - 103 | ### 원자성 문제 104 | - 한 줄의 프로그램 문장이 컴파일러에 의해 기계어로 변경되면서, 이를 기계가 순차적으로 처리하기 위한 여러 개의 Machine Instruction이 만들어져 실행되기 때문에 일어나는 현상 105 | - 예를 들어 프로그램 언어적으로 i++ 문장은 다음과 같은 기계가 수행하는 명령어로 쪼개집니다. 106 | - i를 메모리로부터 읽는다. 107 | - 읽은 값에 1을 더한다. 108 | - 연산한 값을 메모리에 저장한다. 109 | - 멀티 스레드 환경에서는 한 스레드가 각 기계 명령어를 수행하는 동안에 다른 스레드가 개입하여 공유 변수에 접근하여 같은 기계 명령어를 수행할 수 있으므로 값이 꼬이게 됩니다. (race condition) 110 | - 원자성 문제를 해결하기 위해서는 synchronized 또는 atomic을 사용해야 합니다. 111 | - 참고로 원자성 문제를 synchronized 또는 atomic을 통해 해결한다면 가시성의 문제도 해결됩니다. 112 | - 1) synchronized 블럭을 들어가기 전에 CPU Cache Memory와 Main Memory를 동기화 해줍니다. 113 | - 2) atomic의 경우에는 CAS 알고리즘에 의해 원자성 문제와 CPU Cache Memory에 잘못된 값을 참조하는 문제를 동시에 해결해주기 때문입니다. 114 | 115 |
116 | 117 | - `volatile` 사용 : 가시성 문제만 보장합니다. 118 | - 원자성 문제를 보장하지 못합니다. 119 | - `lock` 사용 : 원자성 문제(단일 연산) + 가시성 문제 모두를 보장합니다. 120 | 121 | ### Q) synchronized 선언 시 이는 암묵적으로 수행하는데 세밀하게 control 할 수 있는 명시적인 lock 의 방법으로 뭐가 있을까요? 122 | 123 | - JAVA에서 Monitor 방식의 구현은 두 가지로 나뉩니다. 124 | 125 | - 1. **Implicit(암묵적) Lock (synchronized 키워드)** 126 | - Lock 클래스를 사용하여 직접 lock, unlock 을 구현하는 것이 아니라 내부적으로 객체의 고유 락을 사용하여 접근을 제어하기 때문에 암묵적이라고 분류됩니다. 127 | 128 | - 2. **Explicit(명시적) Lock (java.util.concurrent.locks)** 129 | - 직접 Lock 객체를 명시적으로 생성하여 제어할 수 있습니다. 130 | - `java.util.concurrent.lock` 패키지 : 131 | - concurrent.locks 패키지는 내부적으로 synchronized를 사용하여 구현되어 있지만 더욱 유연하고 세밀하게 처리하기 위해 사용됩니다. 132 | - 고유 락 외에 직접 동기화를 구현할 수 있는 lock 구현체를 제공합니다. 이들은 보다 다양한 기능을 제공하고 있으며, 이를 통해서 코드에서 lock 획득과 해제를 구현할 수 있습니다. 133 | - `ReentrantLock` : Lock의 구현체로 임계 영역의 시작과 종료 지점을 직접 명시할 수 있습니다. (가장 일반적인 lock / 특정 조건에서 lock 을 반납하고 이후에 다시 재진입 시도 가능 / lock 을 걸고 싶은 위치에서 ReentrantLock 객체의 lock() 메서드를 호출하고, 해제하고 싶은 위치에서 unlock() 을 호출하여 lock 을 제어 가능) 134 | 135 | - `ReentrantReadWriteLock` : 공유 자원에 여러 개의 스레드가 read 가능하고, write는 한 스레드만 가능한 인터페이스로 읽기를 위한 lock과 쓰기를 위한 lock을 별도로 제공합니다. ( 읽기 락과 쓰기 락을 함께 제공 ) 136 | 137 | - `java.util.concurrent.atomic`의 **atomic** : 138 | - 해당 타입으로 선언한 단일 변수에 대하여 atomic operations 를 지원하는 타입입니다. 139 | - atomic 타입은 사용 시에 내부적으로 **CAS (Compare And Swap)** 알고리즘을 사용하여 값을 비교하는 방식으로 동기화를 적용합니다. 140 | - 이 방식을 사용하여 따로 lock 을 사용하지 않고 동기화를 처리할 수 있습니다. 141 |
142 | CAS (Compare And Swap) 143 | 144 | - CAS 알고리즘은 변수의 값을 확인할 때, **현재 스레드의 데이터를 실제 메모리에 저장된 데이터와 비교하여 두 값이 일치하는 경우에만 해당 값을 사용**할 수 있도록 합니다. 145 | - 현재 연산 중에서 스레드의 값과 메모리의 값이 다른 경우 중간에 다른 스레드를 통한 작업이 있었던 것으로 판단하여 write 를 중단하고 작업을 재시도하도록 한다. 146 | 147 |
148 | 149 | ### Q) 자바에서 thread 를 생성하는 방법과 실행하는 방법을 설명해주세요. 150 | - Java에서 Thread를 생성하는 방법은 두가지가 존재합니다. 151 | - 1. Thread 클래스를 상속 받아 run 메서드를 오버라이딩 하는것 152 | - 2. Runnable 인터페이스를 Implements 하여 run 메서드를 정의하는것 153 | 154 | ### Q-1) thread 실행 시 run()으로 수행할 때와 start()로 수행할 때와의 차이를 설명해주세요. 155 | ![image](https://user-images.githubusercontent.com/76711238/236792234-e1488ca8-1aa1-4792-abe1-17149a27ab37.png) 156 | - jvm은 ‘data, code, stack, heap’ 영역으로 구성되어 있습니다. 157 | 여기서 프로세스 내부의 thread들은 data, code, heap 영역을 공유하게 됩니다. 158 | - **start()** 메서드는 각 쓰레드마다 call-stack을 새로 만들어 작업을 합니다. 즉 새로 thread를 실행하는 것입니다. (개인의 thread를 만들고 개인의 call stack을 이용) 159 | - **run()** 메서드는 메인쓰레드의 call-stack을 공유하여 작업을 합니다. 즉 기존에 있던 thread를 실행하는 것입니다. 160 | 161 | ### Q-1) 일반 방식에서 main thread가 종료되면 어플리케이션이 종료될 텐데, 멀티스레드 방식에서 main thread는 언제 종료되나요? 162 | - 멀티쓰레드 환경에서 마지막 thread까지 모두 수행을 종료할 때 어플리케이션이 종료됩니다. 163 | 164 | 165 | 166 | #### 사진 & 내용 출처 167 | 168 | https://tecoble.techcourse.co.kr/post/2021-10-23-java-synchronize/ 169 | 170 | https://lordofkangs.tistory.com/28 171 | 172 | https://bgpark.tistory.com/161 173 | 174 | https://yeonbot.github.io/java/ThreadLocal/ 175 | 176 | https://madplay.github.io/post/java-threadlocal 177 | 178 | https://jgrammer.tistory.com/entry/Java-%ED%98%BC%EB%8F%99%EB%90%98%EB%8A%94-synchronized-%EB%8F%99%EA%B8%B0%ED%99%94-%EC%A0%95%EB%A6%AC 179 | 180 | https://a07274.tistory.com/268 181 | 182 | https://steady-coding.tistory.com/554 183 | 184 | https://yhmane.tistory.com/215 185 | -------------------------------------------------------------------------------- /Java/Wrapper.md: -------------------------------------------------------------------------------- 1 | # Wrapper 2 | ### Wrapper 클래스란 3 | * **기본 자료타입(Primitive Type)을 객체로 다루기 위해서 사용하는 클래스**를 말합니다. 4 | 5 | #### Q) Wrapeer 클래스는 언제 사용하는가 6 | - 기본 값 간의 식별성으로 구분해야 될 때 사용할 수 있고, null을 허용해야 하는 경우 사용 할 수 있습니다. 7 | - 제너릭 및 Collection, Arrays 등을 사용 할 때 스트림을 쓰지 않고 컬렉션 API를 사용하기 위해서는 대부분 제너릭으로 인해 클래스 타입을 사용해야하기 때문에 이럴 경우에도 사용합니다. 8 | 9 | #### Q) Boxing(박싱), Unboxing(언박싱)에 대해서 설명해주세요. 10 | ![사진1](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrryw5%2FbtrbhYdkjlR%2Fkd888gYsrnmPgcTGuXNpXk%2Fimg.png) 11 | - Primitive Type 과 Wrapper class 는 서로 상호 변환이 이루어집니다. 12 | - **박싱 : Primitive -> Wrapper** 13 | - **언박싱 : Wrapper -> Primitive** 14 | - JDK 1.5 버전부터는 AutoBoxing/Unboxing이 생겨 따로 형변환 처리를 해주지 않아도 변환됩니다. 15 | 16 | 17 | ### 참고이미지 18 | [사진1](https://tragramming.tistory.com/97) -------------------------------------------------------------------------------- /Network/ApplicationLayer.md: -------------------------------------------------------------------------------- 1 | # 응용 계층 2 | 3 | ### 1. 응용 계층에 대해서 설명해주세요. 4 | * 응용 계층은 사용자 또는 애플리케이션이 네트워크에 접근할 수 있도록 해주는 영역이다. 사용자를 위한 인터페이스를 제공하며, 사용자에게 보이는 유일한 계층입니다. 5 | * 주된 프로토콜로 HTTP, FTP, SMTP, POP3, IMAP, Telnet 등과 같은 많은 프로토콜이 존재합니다. 6 | 7 | ### 2. DNS에 대해서 설명해주세요. 8 | * DNS 프로토콜은 응용 계층에 위치한 프로토콜입니다. 9 | * DNS가 하는 주된 일은 IP를 사람들이 보기 편한 도메인으로 변환하거나, 도메인을 IP로 변환하는 일을 담당합니다. 10 | * DNS의 특징으로 크게 2가지로 볼 수 있습니다. 11 | 1. 추가적으로 복잡한 호스트네임에 대하여 여러가지 별칭을 가질 수 있습니다. 이로 인해 메일서버 별칭 같은 것도 가능합니다. ex) `relay1.west-coast.enterprise.com` -> `enterprise.com`, `www.enterprise.com` 12 | 2. 같은 도메인에 대해서 여러 IP 지정이 가능합니다. 따라서 같은 도메인 질의시 DNS는 IP를 돌려가면서 사용합니다. 13 | * 사용자가 직접 사용하는 프로토콜이 아니라, 웹 브라우저가 실행하는 프로토콜입니다. 14 | * 포트 번호는 53번 포트를 사용하고, 평소에는 UDP/53 을 사용하다가 두 가지 경우에만 TCP/53을 사용합니다. 15 | 1. 전송데이터가 512 Bytes 이상 16 | 2. Zone transfer(존 영역을 전송할 때) 17 | 18 | ### 3. DHCP에 대해서 설명해주세요. 19 | * DHCP는 호스트의 IP주소와 각종 TCP/IP 프로토콜의 기본 설정을 클라이언트에게 자동적으로 제공해주는 프로토콜로 동적주소 할당 프로토콜입니다. 20 | * DHCP는 UDP 프로토콜을 사용합니다. 클라이언트가 IP가 설정이 안되어 있는 경우 DHCP 서버를 찾아야 하는데, 이 과정에서 클라이언트는 DHCP 서버의 위치를 모르기 때문에 브로드캐스팅을 통해 DHCP 서버를 찾아야합니다. 이 과정에서 신뢰성보다는 빠른 속도가 중요하기 때문에 UDP를 사용합니다. 21 | * **[장점]** : DHCP는 PC의 수가 많거나 PC 자체의 변동사항이 많은 경우 IP 설정이 자동으로 되어서 효율적으로 사용이 가능하고 IP 충돌을 막을 수 있습니다. 22 | * **[단점]** : DHCP 서버에 의존하기 때문에 서버가 다운되면 IP 할당이 제대로 이루어지지 않는다는 문제가 있습니다. 23 | 24 | ### 4. Https에서 서버가 인증서를 발급받고 클라이언트와 TLS(SSL) HandShake에 대해서 설명해주세요. 25 | ![SSL HandShake](https://i.imgur.com/YIfy1wK.png) 26 | 1. 먼저 서버는 CA에게 일정 금액을 제공하고 SSL 인증서를 받습니다. 27 | 2. 클라이언트가 서버에게 메시지를 전송합니다. 메시지에는 TLS버전, 암호화 알고리즘, 무작위 바이트 문자열이 포함됩니다. 28 | 3. 서버가 클라이언트에게 메시지를 전송합니다. 메시지에는 SSL 인증서, 선택한 암호화 알고리즘, 무작위 바이트 문자열이 포함됩니다. 29 | 4. 클라이언트는 해당 SSL 인증서가 신뢰할만한지 CA에 검증합니다. 30 | 5. 클라이언트는 서버에서 제공한 무작위 바이트 문자열을 서버의 공개키로 암호화된 premaster secret key를 서버에 전송합니다. 31 | 6. 서버는 premaster secret key를 개인키로 복호화합니다. 32 | 7. 클라이언트와 서버는 클라이언트의 무작위 바이트 비트열, 서버의 무작위 바이트 비트열, premaster secret key를 통해 검증하고, 세션 키를 생성합니다. 이때, 양쪽 다 같은 키(대칭키)가 생성됩니다. 33 | 8. 클라이언트는 세션 키로 암호화된 완료 메시지를 전송합니다. 34 | 9. 서버도 세션 키로 암호화된 완료 메시지를 전송합니다. 35 | 10. HandShake가 완료되고, 세션 키를 이용해 통신을 진행합니다. 이 과정에서는 대칭키 암호화를 사용하여 통신합니다. 36 | 37 | ### 5. CORS에 대해서 설명해주세요. 38 | * CORS에 대해서 설명하기 전에 먼저 SOP에 대해서 알아야합니다. 39 | * **SOP(Same-Origin-Policy)** 는 **같은 출처에서만 리소스를 공유할 수 있다는 규칙입니다.** SOP를 도입하게 된 이유는 출처가 다른 두 애플리케이션이 자유로이 소통을 하게 된다면 해커가 **CSRF(Cross-Site Request Forgery)** 혹은 **XSS(Cross-Site Scripting)** 등의 방법을 이용해서 개인 정보를 탈취할 수 있기 때문입니다. 40 | * SOP는 **Origin을 Scheme, Host, Port 3가지가 동일하다면 동일한 것으로 판단**을 합니다. 41 | * 세상이 발전하게 되면서 다른 출처의 리소스를 사용해야 하는 상황이 적지않게 발생하게 되면서 CORS가 생겨났고, **CORS**는 **SOP 정책을 위반하더라도 CORS 정첵에 따르면 다른 출처의 리소스라도 허용을 하게 해주는 정책**입니다. 42 | * **[기본 동작]** 43 | 1. 다른 출처의 리소스 요청시 요청 헤더에 origin 이라는 필드에 요청을 보내는 출처를 담아서 보낸다. 44 | 2. 서버가 응답시 응답 헤더에 Access-Control-Allow-Origin 이라는 필드에 허용가능한 리소스 출처를 담아서 보낸다. 45 | 3. 브라우저가 요청 헤더에 보냈던 origin과 Access-Control-Allow-Origin 을 비교하여 유효한 응답인지 결정한다. 46 | 47 | * **CORS는 크게 3가지 시나리오**로 동작합니다. 48 | 49 | 50 | 51 | #### Preflight Request 52 | ![Preflight Request](https://evan-moon.github.io/static/c86699252752391939dc68f8f9a860bf/21b4d/cors-preflight.png) 53 | - 일반적으로 웹 애플리케이션을 개발할 때 마주치는 시나리오 입니다. 요청을 한 번에 보내지 않고 예비 요청과 본 요청으로 나누어서 본 요청으로 보내기 전에 브라우저 스스로 이 요청을 보내는 것이 안전한지 확인하는 방식입니다. 54 | #### Simple Request 55 | ![Simple Request](https://evan-moon.github.io/static/d8ed6519e305c807c687032ff61240f8/21b4d/simple-request.png) 56 | - 예비 요청을 보내지 않고 바로 서버에게 본 요청을 보낸 후 브라우저가 Access-control-allow-origin을 확인하는 방식입니다. 이렇게만 보면 Preflight Request보다 속도도 빠르고 좋을 것 같지만 몇 가지 조건이 존재합니다. 57 | 1. HTTP 메서드가 GET, HEAD, POST 이여야만 한다. 58 | 2. Accept, Accept-Language, Content-Language, Content-type, DPR, DownLink, Save-Data, viewport-width, width 요청 헤더만 사용이 가능합니다. 59 | 3. Content-type 중에서도 `application/x-www-form-urlencoded`, `multipart/form-date`, `text/plain`만 허용됩니다. 60 | - 최근에는 text/xml, application/json을 사용한 api 통신을 많이 사용하기 때문에 조건 충족이 까다롭습니다. 61 | #### Credentialed Request 62 | - 인증된 요청을 추가하여 사용하는 방식입니다. CORS 기본 방식보다는 다른 출처간 통신에서 보안을 강화하고 싶을 때 사용합니다. 63 | XMLHttpRequest 혹은 fetch API는 비동기 API로써 쿠키 혹은 인증과 관련된 헤더를 요청에 담지 않는데, 이러한 요청을 달 수 있게 도와줍니다. 64 | - 인증 옵션은 3가지로 구분합니다. 65 | 1. same-origin : 같은 출처 간 요청에만 인증 정보를 담을 수 있다. 66 | 2. include : 모든 요청에 인증 정보를 담을 수 있다. 하지만 `Access-Control-Allow-Origin: *`로 모든 URL을 허락하는 상황은 불가능하고, 응답 시 URL을 명시해주어야 하고, `Access-Control-Allow-Credentials: true` 헤더를 추가해주어야 한다. 67 | 3. omit : 모든 요청에 인증 정보를 담지 않는다. 68 | 69 | ### 참고자료 주소 70 | - https://steady-coding.tistory.com/504 71 | - https://galid1.tistory.com/53 72 | - https://kanoos-stu.tistory.com/46 73 | - https://wayhome25.github.io/cs/2018/03/11/ssl-https/ 74 | - https://evan-moon.github.io/2020/05/21/about-cors/ 75 | - https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F -------------------------------------------------------------------------------- /Network/HTTP,HTTPS.md: -------------------------------------------------------------------------------- 1 | # HTTP & HTTPS 2 | 3 | HTTP 4 | - 인터넷에서 클라이언트, 서버간 데이터와 리소스를 교환할수있게 해주는 기본 프로토콜 5 | - 요청과 응답이 이전 요청,응답과 독립적인 stateless한 프로토콜 6 | 7 | HTTPS 8 | - HTTP에 데이터를 주고받는과정에 보안적인 요소가 추가된 프로토콜 9 | 10 | ### Q) HTTP의 비연결성과 Stateless에 대해 설명해주세요 11 | 12 | - HTTP는 이전 요청과 응답에 독립적인 Stateless한 특징덕분에 확장성과 캐시가능성의 이점이있습니다. 13 | - 각 요청이 독립적이기때문에 서버는 상태정보를 유지할필요가 없으며 이는 리소스를 관리하기 용이해지고 더 많은 요청을 동시에 처리할수있습니다. 14 | 15 | - HTTP는 요청과 응답을 주고받은후 연결을 끊는 특성이있습니다. 16 | 17 | ### Q) HTTP는 항상 Stateless한가요? 상태를 유지해야하는경우는 어떤경우인지 설명해주세요 18 | 19 | - 장바구니같이 사용자가 담아둔 정보를 유지해야하는경우가 있을수있는데 이런경우 상태유지를위한 쿠키,세션과같은 개념이 필요합니다. 20 | 21 | ### Q) 쿠키를 사용했을때 단점에대해 설명해주세요 22 | 23 | - 가장 큰 단점은 쿠키의 데이터가 쉽게 노출될수있다는 점이있고 용량 제한이 4KB까지있어서 많은 데이터를 담을순없고, 쿠키사이즈가 커질수록 네트워크 부하가 심해질수있습니다. 24 | 25 | > #### Q) 쿠키는 클라이언트 어디에 저장되나요? 26 | 27 | 서버가 Set-Cookie헤더가 포함된 응답을 클라이언트에 보낸다면 브라우저가 쿠키를 수신해 로컬에 저장합니다. 28 | 브라우저가 쿠키를 저장/관리하게됩니다. 29 | 30 | > #### HTTPS 설정하기위한 인증서 발급과정과 서버가 어떻게 인증서 발급받고 사용하는지 설명해주세요 31 | 32 | 1. CSR(인증서 서명요청)에 도메인이름, 조직세부정보, 서버의 공개키를 담아 생성한다. 33 | 34 | 2. 서버에서 CSR을 인증기관에 제출한다. 35 | 36 | 3. 인증기관은 유효성을 확인하고 인증서를 발급해준다. 37 | 38 | 4. 인증기관으로부터 받은 인증서를 서버에 설치하고 HTTPS연결에 인증서를 사용하도록 구성한다. (개인키는 서버에 안전하게 저장) 39 | 40 | 41 | > #### SSL Handshake가 무엇인가요 42 | 43 | 클라이언트,서버가 보안연결을 할때 발생하는 프로세스 44 | - 클라이언트에서 메시지(SSL/TLS버전 포함)를 서버에 전송해 handshake를 시작하고 서버가 메시지를 수신하면 서버는 메시지로 응답한다. 45 | 46 | - 서버는 클라이언트와 서버 모두 호환되는 가장높은 SSL/TLS버전을 선택하고 공개키가 포함된 디지털 인증서를 보낸다 47 | 48 | - 클라이언트는 인증서의 신뢰성, 무결성확인한다. 49 | 50 | - 인증서 유효성 검사 성공시 클라이언트가 임의의 세션키를 생성해 인증서에서 얻은 서버의 공개키로 암호화해 서버로 보낸다. (서버에서만 해독될수있게) 51 | 52 | - 서버에서 암호화된 세션키를 수신하여 서버의 개인키를 사용해 복호화한다. 53 | 54 | - 클라이언트, 서버 모두 동일한 세션키를 가지게된다 55 | 56 | 57 | > #### SSL TLS 차이 58 | 59 | TLS가 SSL에서 업데이트된 안전한 버전이며, 두 용어는 종종 같은의미로 사용된다. 60 | 더 나은 보안, 호환성을 위해 SSL버전이아닌 TLS를 사용하기도한다. 61 | 62 | ### Q) keep-alive 기능에 대해 설명해주세요 63 | 64 | HTTP 통신을 하기위해 TCP연결을 먼저 하고 통신을 해야하는데 매번 요청이있을때마다 TCP연결을 하고 HTTP 통신을 하는게 아닌 TCP 연결을한번 해놓고 여러번의 HTTP통신을 할수있게끔 TCP연결을 유지하는 것입니다 65 | 66 | ### Q) GET,POST 메서드의 차이 67 | 68 | GET: 리소스를 검색,조회할때 사용되는 메서드 69 | POST: 리소스를 생성하거나 어떤요청을 처리할때 사용되는 메서드 70 | 71 | > #### Q) 멱등성이란? GET은 멱등한가요? 72 | 73 | 멱등성은 요청을 여러번 보냈도 결과가 같은것을 의미합니다. 74 | GET메서드는 특정한 리소스를 가져오도록 요청하는 메서드이며, 서버의상태를 변경시키지 않기때문에 멱등합니다 75 | 76 | ### Q) PUT과 PATCH의 차이 77 | 78 | PUT은 리소스를 아예 붙여넣기(대체)하기때문에 멱등한 메소드이고 79 | PATCH는 변화된 리소스부분만 수정하는 메소드로 멱등하지않다. 80 | 81 | 82 | ### Q) HTTP 1.1, HTTP 2 차이 83 | 84 | - 다중화 : HTTP 1.1은 단일 TCP연결로 한번에 하나의 요청만 보낼수있는데 HTTP 2는 동시에 여러요청을 보내고 받을수있다. 85 | 86 | - 헤더 압축 : HTTP2에서 헤더압축 사용해서 전송 데이터양을 줄여서 성능 향상 87 | 88 | - 우선순위지정 : 각 요청의 우선순위를 지정할수있다. 89 | 90 | > #### Q) HTTP 1.0, HTTP 1.1 차이 91 | 92 | - Connection: Keep-alive 속성이 추가되었다. 1.0에서는 요청마다 새로운 TCP세션을 맺어야했는데 1.1에선 TCP 커넥션을 지속한다. 93 | 94 | - HTTP 1.0에선 요청에대한 응답을 기다리고 다음 요청을 봅낼수있었는데 HTTP 1.1 에선 파이프라이닝기능을 통해 요청을 병렬로 처리할수있어 응답속도가 훨씬 빨라지게 되었다. 95 | 96 | - 프록시 인증헤더가 추가되었다. 97 | 98 | ### Q) HTTP 3에대해 설명해주세요 99 | 100 | - UDP기반의 프로토콜 QUIC를 사용하는 프로토콜 101 | - UDP프로토콜을 선택하여 TCP프로토콜의 3way handshake 과정을 줄이고 한번의 왕복만으로 새 서버와 연결 + 암호화를 결합하는 방식을 사용한다 102 | 103 | > #### Q) HTTP3에서 UDP를 사용하면서 TCP 의 신뢰성을 보장하는 방법에대해 설명해주세요 104 | 105 | QUIC 의 고유한 신뢰성있는 메커니즘이 포함되어있다. 안정적인 패킷전달, 손실패킷 재전송, 혼잡제어를 제공한다. 106 | 이는 TCP가 제공하는 손실제어 메커니즘을 따른다. 107 | 108 | 109 | 110 | ### Q) 기존에 id가 1인 user의 이름(이영진), 성별(남자)이 존재하는상황에서 PUT /edit/1로 이름(김영진)으로 보내게된다면 어떻게 동작할까? 111 | 112 | PUT 메소드는 데이터를 갈아치워서 덮어쓰기때문에 기존에있었던 이름(이영진), 성별(남자)의 데이터는 날아가고 **이름(김영진)**만 저장된다. 113 | 114 | ### Q) 등록을 할때 POST를 사용해야하는경우, PUT을 사용해야하는경우가 있는데 어떻게 구분할것인가? 115 | 116 | uri에 식별자가 포함되냐 안되냐로 구분할수도있고, 멱등성의 유무로도 구분할수있다. 또한, 데이터를 덮어써도 되는상황인지 아닌지에 따라서도 구분할수있겠다. 117 | 118 | > #### Q) POST 방식으로 응답코드를 201로 한다면 응답헤더에는 뭐가 실릴수있나요? 119 | 120 | 121 | 201 Created는 서버가 요청을 정상처리했고 새로운 리소스가 생겼다는 의미이다. 이때 Content-Location 으로 생성된 리소스의 위치를 명시할수있다. 122 | 123 | 124 | ### Q) HTTPS 의 장단점 125 | 126 | 장점 127 | - 통신을 암호화하기때문에 보안에 유리하다 128 | - 인증서를 사용하기때문에 신뢰할수있는 통신을 할수있다. 129 | 130 | 단점 131 | - 암호화,복호화 알고리즘이 추가되어 HTTP에 비해 오버헤드가있을수있다. 132 | - 인증서 설치,갱신 등의 관리가 필요하다 133 | 134 | ### Q) HTTP 캐싱에대해 설명해주세요 135 | 136 | private cache : 한명의 사용자만 사용하는 캐시, 브라우저가 시도하는 모든 HTTP 요청은 브라우저 캐시로 라우팅되어 유효한 캐시가 있다면 캐싱한다. 137 | 138 | 공유 프록시 cache : 한명 이상의 사용자에 의해 재사용되는 응답을 저장하는캐시, 특정지역 네트워크의 일부분으로 웹프록시를 설치해두고 캐싱할수있다. 139 | 140 | ### Q) 응답코드 401, 403의 차이를 설명해주세요 141 | 142 | 401응답코드는 인증되지않은 사용자가 인증이 필요한API에 요청한경우 사용합니다. 143 | 403응답코드는 인증은 되었지만 권한이 부족한 사용자가(정회원이 필요한데, 준회원이 요청할때) 요청한경우 사용합니다. 144 | 145 | 146 | ### Q) 인증 vs 인가 147 | 148 | 인증: 사용자의 신원을 검증한다. ID, password 등을 확인하든 이메일로 인증하는 등 149 | 150 | 인가: 사용자에게 특정 리소스나 기능에 액세스 할수있는 권한을 부여하는 프로세스 151 | 152 | 153 | ref 154 | - https://rachel-kwak.github.io/2021/03/08/HTTPS.html 155 | -------------------------------------------------------------------------------- /Network/Internet Layer (Network Layer).md: -------------------------------------------------------------------------------- 1 | # TCP/IP - Internet Layer (OSI - Network Layer) 2 | 3 | ![image](https://github.com/kim-se-jin/CS-JAVA-Study/assets/76711238/40469851-d375-4dfe-8a4f-493ea5f7e23d) 4 | 5 | - 네트워크 상에서 데이터의 전송을 담당하는 계층으로 서로 다른 네트워크 간의 통신을 가능하게 하는 역할을 수행합니다. (연결성 제공) 6 | - 단말을 구분하기 위해 논리적인 주소로 IP 주소를 할당하게 되고 이 IP 주소로 네트워크 상의 컴퓨터를 식별하여 주소를 지정할 수 있도록 합니다. 7 | - 네트워크끼리 연결하고 데이터를 전송하는 기기인 '라우터'라고 하며, 라우터에 의한 네트워크 간의 전송을 '라우팅'이라고 합니다. 8 | - 라우터가 내부의 라우팅 테이블(Routing Table)을 통해 경로 정보를 등록하여 데이터 전송을 위한 최적의 경로를 찾는데, 이렇게 출발지와 목적지 간의 데이터 전송 과정을 가리켜 End-to-End 통신이라고 부릅니다. 9 | 10 | |제목|내용| 11 | |------|---| 12 | |데이터 전송 단위|패킷(packet))| 13 | |전송 주소|IP| 14 | |프로토콜 |IP, RIP, ARP, ICMP| 15 | |장비 | 라우터| 16 | OSI : 3계층 네트워크 계층(Network Layer) 17 | 18 | - 상위 레벨 데이터를 패킷 안으로 캡슐화하여 데이터 종류에 상관없이 한 호스트에서 다른 호스트로 그 패킷들을 라우팅해줍니다. 19 | 20 | ### Q) IP 주소와 MAC 주소의 차이에 대해 설명해주세요. 21 | 22 | - 공통점 : 네트워크 통신에서 통신기기의 식별번호 역할 23 | 24 | **IP주소** 25 | - 소프트웨어 기반으로 생성된 논리적 주소(Logical Address)입니다. 26 | - 통신기기마다 고유하게 할당되어 있는 것이 아니라, 대부분 통신사에 일정 금액을 지불하고 받아오는 것이기 때문에 경우에 따라 바뀔 수 있습니다. 27 | 28 | **MAC 주소** 29 | - 하드웨어 기반으로 생성된 물리적 주소(Physical Address)입니다. 30 | - 통신기기의 하드웨어 자체에 부여된 고유한 식별번호를 나타내며 변경될 수 없다. 31 | - 이러한 특성 때문에, MAC 주소는 외부에서 내부의 사설 아이피로 통신 요청을 할 때 중요한 역할을 합니다. 사설 아이피는 외부에서 볼 수 없기 때문에 외부에서는 어떤 사설 아이피가 최종 목적지인지 알 수가 없는데, 이 때 최종 목적지의 MAC주소를 알고 있다면 아이피 주소에 구애받지 않고 원하는 목적지까지 도달할 수 있게 됩니다. 32 | 33 | - MAC 주소는 데이터 링크 계층에서 작동하며, IP 주소는 네트워크 계층에서 작동합니다. 34 | - MAC 주소를 찾아주는 게 ARP 프로토콜, IP 주소를 찾아주는 건 RARP 프로토콜입니다. 35 | 36 | ### Q) 신뢰성 없는 IP 네트워크 계층을 위한 프로토콜을 설명해주세요. 37 | - ICMP 입니다. ICMP는 **TCP/IP에서 IP 패킷을 처리할 때 발생되는 문제를 알려주는 프로토콜**입니다. 38 | - IP에는 오로지 패킷을 목적지에 도달시키기 위한 내용들로만 구성되어 있습니다. 39 | - 따라서 정상적으로 목적지 호스트로 도달하는 경우 IP에서 통신이 성공하고 종료되므로 아무런 문제가 없습니다. 40 | - 그러나 전달해야 할 호스트가 꺼져 있거나, 선이 단절된 비정상적인 경우 이 패킷 전달을 의뢰한 출발지 호스트에 이러한 사실을 알려야하지만, IP에는 그런 에러에 대한 처리 방법이 명시되어있지 않습니다. 41 | - 이러한 IP의 부족한 점을 메꾸기 위하여 사용되는 것이 ICMP 프로토콜이다. 42 | - ICMP는 도착지 호스트가 없거나, 포트가 닫혀 있는 등의 에러 상황이 발생할 경우 **IP헤더에 기록되어 있는 출발지 호스트로 에러에 대한 정보를 보내주는 역할**을 합니다. 43 | 44 | > 네트워크 문제로 인해 IP 패킷이 전달되지 않는 경우 라우터와 같은 오류보고 프로토콜 네트워크 장치가 소스 IP 주소로 오류 메시지를 생성하는 데 사용됩니다. ICMP 는 패킷 전달을 위해 라우터, 서비스 또는 호스트에 도달 할 수 없다는 인터넷 게이트웨이 를 나타내는 메시지를 소스 IP 주소로 작성하고 보냅니다 . 45 | 46 | ### Q-1) ICMP 의 TTL 을 설명해주세요. 47 | - 패킷의 생존 시간을 의미합니다. 48 | - IP 패킷 내에 있는 값 으로서, 그 패킷이 네트워크 내에 너무 오래 있어서 버려져야 하는지의 여부를 라우터에게 알려주는 역할을 합니다. 49 | - TTL 은 일정시간을 초단위로 지정하고, 설정 시간이 지나면 패킷을 버리도록 하기위해 고안한 방법입니다. 50 | - 각, Router는 TTL 패킷이 날라올때 TTL Value를 1씩 감소시킵니다. 51 | - TTL 값이 0이 되었을때는 라우터는 그것을 감지하여 해당 패킷을 버리고 ICMP 메세지를 발신지 host 에게 보냅니다. 52 | 53 | ### Q-2) ICMP 의 취약점을 설명해주세요. 54 | - 1. IP Spoofing : IP 주소를 속여서 발생되는 ICMP로 공격하는 것 55 | - 대응 56 | > 외부에서 들어오는 패킷 중에서 출발지 IP주소에 내부망 IP 주소를 가지고 있는 패킷을 라우터 등에게 패킷필터링을 사용해서 막습니다. 그러나 내부망 사용자에 의한 공격을 막을 수 는 없으므로 각 시스템에 TCP Wrapper, ssh를 설치해서 운영하고, rlogin 등과 같이 패스워드의 인증과정이 없는 서비스를 사용하지 않도록 합니다. 57 | 58 | - 2. Ping of Death : 죽음의 핑으로 규정 크기 이상의 ICMP 패킷으로 시스템을 마비시키는 공격을 말합니다. 59 | - ping을 이용해여 ICMP 패킷을 정상 크기보다 훨씬 크게 만들어 공격 대상에게 보내는 공격입니다. 60 | - <방법> 61 | - 1 .공격자가 구글에게 패킷의 크기를 65500 BYTE나 늘려서 PING을 보냅니다. 62 | 63 | - 2. 크기가 큰 패킷은 네트워크 상에서 분할되어 목적지로 전송되므로 65500BYTE의 패킷은 100BYTE의 작은 패킷들로 분할되어 구글에게 가게됩니다. 64 | 65 | - 3. 분할되어진 수많은 패킷을 받은 공격 대상은 부하가 발생해 죽게됩니다. 66 | - 대응 67 | > 가장 간단한 방법은 ICMP 패킷을 막는 것입니다.서버의 앞단 혹은 서버에서 ICMP 패킷을 블로킹해주는 설정을 통해 '죽음의 핑'을 피할 수 있습니다. 68 | - IDS,IPS 임계치 설정 69 | 70 | ### Q) 네트워크 계층에서 어떻게 빠르고 안전하게 데이터를 운반하는지 설명해주세요. 71 | - 72 | ### Q-1) 라우팅 알고리즘에 대해 설명해주세요. 73 | 74 | - 1. **정적 라우팅** 75 | - 정적 라우팅은 라우팅 테이블에 경로를 수동으로 추가해야하는 프로세스입니다 . 76 | - **장점** 77 | - a. 수동으로 정책을 부여하기 때문에 라우터 CPU에 오버헤드가 없어진다. 78 | - b. 네트워크 관리자가 라우팅 동작을 모두 제어할 수 있기 때문에 보안상 더 유리한 부분이 있다. 79 | - **단점** 80 | - a. 네트워크 규모가 커질수록 네트워크 관리자의 작업량이 많이 투입된다. 81 | - b. 라우팅 정보가 수동으로 되어 있어 관리자가 실수로 인해 네트워크 정보를 잘 못 입력할 수 있는 인재가 발생할 수 있다. 즉, 네트워크 관리자가 사내 네트워크 구성을 정보를 잘 알고 있어야 한다. 82 | - c. 네트워크 구성 변경에 따라 end to end 트래픽이 라우팅이 되지 않을 때 백업 구성이 되지않아 관리자가 경로를 재구성할 때까지 사용할 수 없다. 83 | 84 | - 2. 동적 라우팅 85 | - 동적 라우팅은 라우팅 테이블에서 경로의 현재 상태에 따라 경로를 자동으로 조정합니다. 86 | - 동적 라우팅은 프로토콜을 사용하여 네트워크 대상과 도달하는 경로를 검색합니다. 87 | - 하나의 경로가 다운되면 네트워크 대상에 도달하도록 자동 조정됩니다. 88 | - **장점** 89 | - a. 네트워크 관리자의 라우팅 정책 유지를 위한 작업 리소스가 적다. 90 | - b. 네트워크 구성과 상황에 맞게 최적의 경로를 선택할 수 있다. 91 | - c. end to end 경로 손실이 발생하더라도 백업 경로가 있기 때문에 내결함성을 가진다. 92 | - **단점** 93 | - a. 다른 장비들과 통신하기 위해 더 많은 대역폭을 소비합니다. 94 | - b. 정적 라우팅보다 안전하지 않습니다. 95 | 96 | 97 | ### Q) IP 주소를 절약하기 위한 방법을 설명해주세요. (IPv6 등장 이후) 98 | - 공인 IP, 사설 IP 방식을 사용해 IP 주소의 고갈을 방지합니다. 99 | 100 | - **공인 IP** 101 | - 전 세계에서 유일 102 | - 외부, 내부 상관없이 해당 IP에 접속 103 | - **사설 IP** 104 | - 하나의 네트워크 안에서 유일 105 | - 내부에서만 접근이 가능 106 | 107 | - 사설망이란 공유기를 사용한 인터넷 접속 환경일 경우 공유기까지는 공인 IP 할당을 합니다. 108 | - 이후 공유기에 연결되어 있는 가정이나 회사의 각 네트워크 기기에는 사설 IP를 할당하여 그룹으로 묶는 방법입니다. 109 | 110 | > 쉬운 비유 111 | - 일종의 반장을 뽑는 것과 같다. 112 | - 학교의 회의에 참여하는데 모든사람이 참여할수 없으니 (모든 학교의 각 반에게 공인 IP 할당할 수 없음 - 고갈 위험 존재) 학교의 대표 주자인 반장(게이트웨이(Gateway)- 하나의 공인IP 소유)이란걸 뽑는다. 113 | - 그리고 그 반장은 대표로 나가서 학생들의 의견을 대신 전달하며, 학교 회의 내용을 다시 학생들에게 전달한다. 114 | - 여기서 반장이 게이트웨이(Gateway)로 비유할수 있으며, 반을 사설망 (사설 IP 소유), 학생들은 각 전자기기들, 학교를 인터넷으로 비유하면 딱 들어 맞게 된다. 115 | 116 | - ![image](https://user-images.githubusercontent.com/76711238/236821903-a5b7fb6b-1f6b-48ef-8191-7f999c895c3c.png) 117 | 118 | 119 | ### Q-1) 서브넷 마스크(Subnet Mask)가 무엇인지 설명해주세요. 120 | 121 | - 필요한 네트워크 주소만 호스트 IP로 할당할 수 있게 만들어 네트워크 낭비를 방지하기 위한 32bit 2진수 문자열입니다. 122 | 123 | - 아이피 주소에서 네트워크 주소와 호스트 주소를 나눠주는 역할을 합니다. 124 | 125 | - 호스트(개인)들 간의 네트워크 통신(편지의 교환)은 같은 네트워크 주소/네트워크 대역(같은 국가) 내에서만 이루어 진다고 생각하면 된됩니다. 126 | 127 | - 다른 네트워크 대역의 호스트들과 연결하는 방법은 라우팅(Routing)에 관련이 있습니다. 128 | 129 | - 똑같은 아이피 주소라 하더라도, 서브넷 마스크가 다르면, 아이피 주소가 의미하는 바가 완전히 달라지게 됩니다. 130 | 131 | ### Q-2) 서브넷팅이란 무엇인지 설명해주세요 132 | - 한 개의 네트워크를 서브넷 마스크를 이용해 여러 개의 서브넷 네트워크로 분할 하는 것입니다. 133 | - 서브넷마스크를 이용해 한 개의 네트워크를 여러 개의 서브넷 네트워크로 분할해 네트워크 관리자가 네트워크 성능을 향상시키기 위해 자원을 효율적으로 분배하는 것입니다. 134 | 135 | ### Q) 다른 네트워크와 연결할 시 사용되는 수단은 무엇인 지 설명해주세요 136 | - 게이트웨이(Gateway)입니다. 137 | - 게이트웨이(Gateway)란 한 네트워크(segment)에서 다른 네트워크로 이동하기 위하여 거쳐야 하는 지점입니다. 138 | - 게이트웨이(Gateway)는 **서로 다른 네트워크(이기종 네트워크)를 연결**해줍니다. 139 | - 서로 다른 네트워크의 프로토콜이 다를 경우에 중재 역할을 수행합니다. 140 | 141 | (ex) 142 | ![image](https://user-images.githubusercontent.com/76711238/236821246-79cf58d8-8990-49c7-a51a-efa10b290f89.png) 143 | 144 | - 집 컴퓨터에서 인터넷에 접속하려는 경우 `집 -> 공유기 -> 인터넷 제공 회사 라우터 -> 인터넷망` 경로를 따라갑니다. 145 | - 이 때, 공유기와 인터넷 제공 회사의 라우터는 이전의 단계에서 다음 단계로 넘어 갈 때의 게이트웨이 역할을 담당합니다. 146 | - 인터넷에 접속하기 위하여는 수많은 게이트웨이를 거쳐야합니다. 147 | - 이 때, 거치는 게이트웨이의 수를 홉 수(hop count)라고 합니다. 위의 예제에서는 인터넷에 연결할 때까지 필요한 hop count는 2입니다. 148 | 149 | ### Q) ARP (Address Resolution Protocol)에 대해 설명해주세요 150 | - 목적지 컴퓨터의 IP 주소를 이용하여 MAC 주소를 찾기 위한 프로토콜입니다. 151 | - 네트워크 계층 주소와 데이터 링크 계층 주소 사이의 변환을 담당합니다. 152 | - IP 주소를 물리 주소인 MAC 주소로 변환합니다. 153 | 154 | **ARP 요청 (request)** 155 | - 출발지 컴퓨터가 목적지 주소를 모르면 MAC 주소를 알아내기 위해 네트워크에 브로드캐스트를 합니다. 156 | 157 | **ARP 응답 (reply)** 158 | - 지정된 IP 주소를 가진 컴퓨터는 MAC 주소를 응답으로 보냅니다. 159 | - 이를 통해 출발지 컴퓨터는 이더넷 프레임을 만들 수 있습니다. 160 | 161 | **ARP 테이블** 162 | - 출발지 컴퓨터에서는 MAC 주소와 IP 주소의 매핑 정보를 메모리에 보관합니다. 163 | - 이후 데이터 통신을 할 때 테이블을 참고해 데이터를 전송합니다. 164 | - IP 주소가 변경되면 MAC 주소도 함께 변하기 때문에, 정보를 일정 시간이 지나면 삭제하고 다시 ARP 요청을 합니다. 165 | 166 | ### Q) L3 Switch와 Router의 차이 167 | - L3 스위치는 하드웨어적인 방법으로 목적지를 찾는 방식. 168 | 기존의 Router는 소프트웨어적으로 들어오는 IP를 보고 라우팅을 하였지만 L3 Switch는 주로 MAC Address를 이용하고 추가적으로 IP 주소도 사용하여 라우팅을 수행한다. 169 | - 적용 범위에도 큰 차이가 있는데 라우터는 WAN에 대해서 수행하는 것이 목적이고, L3 Switch는 LAN에 대해서 수행하는 것이 목적이다. 170 | - LAN에 대해서 수행할 때 스위치를 논리적으로 분할해서 사용하는 VLAN 기법을 사용한다. 171 | 172 | #### 사진 & 내용 출처 173 | 174 | https://hahahoho5915.tistory.com/12 175 | 176 | https://blog.naver.com/llhbum/221899395130 177 | 178 | https://melonicedlatte.com/network/2020/04/28/201100.html 179 | 180 | https://velog.io/@hidaehyunlee/%EC%84%9C%EB%B8%8C%EB%84%B7%ED%8C%85subnetting%EC%9C%BC%EB%A1%9C-%EB%84%A4%ED%81%AC%EC%9B%8C%ED%81%AC%EB%A5%BC-%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EA%B4%80%EB%A6%AC%ED%95%98%EC%9E%90 181 | 182 | https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-IP-%EA%B8%B0%EC%B4%88-%EC%82%AC%EC%84%A4IP-%EA%B3%B5%EC%9D%B8IP-NAT-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A7%90-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC#ip_%EC%A3%BC%EC%86%8C%EC%9D%98_%EA%B3%A0%EA%B0%88_%EC%9C%84%ED%97%98 183 | 184 | https://superbono-2020.tistory.com/60 185 | -------------------------------------------------------------------------------- /Network/Network Access Layer (Physical & Data).md: -------------------------------------------------------------------------------- 1 | # TCP/IP - Network Access Layer (OSI - Physical & Data Layer) 2 | 3 | ![image](https://github.com/kim-se-jin/CS-JAVA-Study/assets/76711238/008cd036-165d-481e-8f03-2d866c1b8866) 4 | 5 | - 물리적인 데이터의 전송을 담당하는 계층 6 | - 인터넷 계층과 달리 **같은 네트워크 안에서 데이터가 전송**됩니다. 7 | - 노드 간의 신뢰성 있는 데이터 전송을 담당하며, 논리적인 주소가 아닌 물리적인 주소인 MAC을 참조해 장비간 전송을 하고, 기본적인 에러 검출과 패킷의 Frame화를 담당한다. 8 | 9 | > - 역할 : 실제 데이터인 프레임 송수신 10 | - 데이터 단위 : Frame 11 | - 전송 주소 : MAC 12 | - 프로토콜 : Ethernet 13 | - 장치 : 브릿지, 스위치 14 | 15 | **OSI : 1계층 물리 계층(Physical Layer)** 16 | - 케이블이 연결되어 있는 기기에 대한 신호 전달을 수행하는 계층 17 | - 데이터 링크 계층의 프레임을 받고, 다음 장치에 구리나 광섬유(케이블) 또는 무선 통신 매체를 통신해 전송하기 위한 신호로 바꾸어 줍니다. 18 | - 물리적 매체를 통해 데이터(bits)를 전송하기 위해 요구되는 기능들을 정의합니다. 19 | - USB 케이블, 동축 케이블 등 두 디바이스 간의 실제 접속을 위한 기계적, 전기적 특성에 대한 규칙을 정의합니다. 20 | 21 | |제목|내용| 22 | |------|---| 23 | |데이터 전송 단위|비트(bit)| 24 | |프로토콜 |RS-232, RS-449 등 케이블| 25 | |장비 | 허브, 리피터| 26 | 27 | (+) 허브 : 허브는 여러 대의 기기를 연결하고 신호를 증폭하고 재생하는 역할을 하며 플러딩을 일으킵니다. 28 | 29 | **OSI : 2계층 데이터링크 계층(Data Link Layer)** 30 | - 네트워크 계층 패킷 데이터를 물리적 매체에 실어 보내기 위한 계층 31 | - 포인트 투 포인트(Point to Point) 간 신뢰성있는 전송을 보장하기 위한 계층 32 | - 신뢰성있는 전송을 위해 오류 검출 및 회복을 위한 오류 제어 기능 수행 33 | - 송수신측의 속도 차이 해결을 위해 흐름 제어 기능 수행 34 | 35 | |제목|내용| 36 | |------|---| 37 | |데이터 전송 단위|프레임(frame)| 38 | |프로토콜 | Ethernet(이더넷), PPP, HDLC, ALOHA 등| 39 | |장비 | 브릿지, 스위치 (스위치 안에는 MAC 주소 테이블 존재)| 40 | 41 | ### Q) Mac 주소에 대해 설명해주세요. 42 | 랜카드에 할당된 전 세계에서 유일한 번호로 물리 주소입니다. 43 | - 컴퓨터에 장착된 랜(LAN) 카드를 구별하기 위해 만들어진 식별 번호입니다. 44 | ### Q-1) 어떤 하드웨어 45 | - Network interface card (LAN card) 에 위치합니다. 46 | 47 | ### Q) 데이터 링크 계층에서 자주 사용되는 Ethernet protocol 에 대해 설명해주세요. 48 | - 랜에서 데이터를 주고받기 위한 규칙으로, 허브와 같은 장비에 연결된 컴퓨터와 데이터를 주고받을 때 사용합니다. 49 | - 고유의 MAC 주소를 가지고 이 주소를 이용해 상호간에 데이터를 주고 받을 수 있도록 만들어졌습니다. 50 | - 이더넷에서는 수신처 MAC 주소를 보고 **자기에게 온 것만 받고 다른 프레임은 파기**합니다. (멀티캐스트의 경우 그룹 번호가 들어가있기 때문에 자신이 속한 그룹 번호로 수신처가 적혀있다면 수신) 51 | - CSMA/CD : 이더넷은 CSMA/CD라는 데이터 전송 시점을 늦추는 방법을 사용하여 충돌을 방지합니다. 52 | - 하지만 최근에는 스위치(switch)라는 장비를 사용하면서 CSMA/CD를 사용하지 않습니다. 53 | 54 | ### Q) 처음에 MAC 주소 테이블에 아무것도 존재하지 않을 때 어떻게 MAC 주소 테이블을 채우는지 설명해주세요. 55 | - MAC 주소 테이블에 등록되어 있지 않은 MAC 주소가 들어오면, 송신 포트를 제외한 모든 포트에 데이터를 전송합니다. 이를 `플러딩 (flooding)` 이라고 합니다. 56 | 57 |
58 | MAC 주소 테이블 (MAC address table) 59 | 60 | - 스위치의 포트 번호와 해당 포트에 연결되어 있는 컴퓨터의 MAC 주소가 저장된 데이터베이스입니다. 61 | 스위치에 연결된 컴퓨터가 프레임(데이터)을 전송하면 MAC 주소 테이블을 확인하고 해당 포트로 전송합니다. 62 | - 만약 테이블에 저장되지 않는 주소라면, MAC 주소와 포트 번호를 데이터베이스에 정보를 저장 합니다. 63 | - 이를 MAC 주소 학습 기능이라고 하고, 허브에는 없는 기능입니다. 64 | 65 |
66 | 67 | ### Q) 물리 계층에서 전기 신호가 약해지는 경우, 이를 보완해주기 위해 어떻게 하는지 설명해주세요. 68 | - 긴 케이블(동선)을 지나는 동안 신호가 약해지는데 그렇게 되면 신호의 진폭의 약해져서 수신측에서 데이터를 못 읽을 수도 있습니다. 이러한 문제점을 해결하기 위하여 약해진 신호를 다시 강하게 해주는 증폭기를 사용합니다. 69 | - 신호의 증폭 / 재생 => 허브로! 70 | - 감쇠된 신호를 **허브**를 통해 증폭 / 재생한다. 원래 신호를 증폭하기 위한 기계로 리피터(Repeater)가 있는데, 리피터는 허브처럼 여러개의 기기들을 연결할 수 없다는 단점이 있습니다. 71 | - 그래서 **허브에 신호를 증폭하는 기능을 추가**해 사용하곤 합니다. 72 | - 추가로 신호를 증폭 / 재생하지 않는 허브도 있는데, 이런 허브는 패시브(passive) 허브라고 부르고, 증폭기능을 하는 허브를 액티브(active) 허브라고 부릅니다. 73 | 74 | ### Q) 데이터 링크 계층은 헤더가 붙는 방식이 다른 계층과 다른데, 이를 설명해주세요. 75 | - 트레일러(FCS) 가 붙습니다. 76 | - 트레일러는 데이터 뒤에 붙고, FCS(Frame Check Sequence)라고 부르기도 합니다. 77 | - FCS는 데이터 전송 도중 오류가 발생하는지 확인하는데 사용됩니다. 78 | - 다른 계층에선 단순히 헤더 하나씩만 추가되는데 데이터 링크에서는 FCS 가 추가적으로 붙습니다. 79 | ![image](https://user-images.githubusercontent.com/76711238/236818056-3795767b-29bc-474a-95ab-eca30d058bab.png) 80 | 81 | ### Q-1) 각 계층에서의 데이터를 어떻게 부르는 지 설명해주세요. 82 | - 이미지 참조 83 | ![image](https://user-images.githubusercontent.com/76711238/236815251-373e8061-9be0-4518-b6a5-bf179245d80f.png) 84 | 85 | #### 사진 & 내용 출처 86 | 87 | https://jinmay.github.io/2018/12/09/network/daily-network-first-layer/ 88 | 89 | https://www.google.com/url?sa=i&url=https%3A%2F%2Ffreloha.tistory.com%2F20&psig=AOvVaw3MQJsoUixvuSrJi0DfcJps&ust=1683633451536000&source=images&cd=vfe&ved=0CBMQjhxqFwoTCLicp8DV5f4CFQAAAAAdAAAAABAE -------------------------------------------------------------------------------- /Network/PresentationLayer.md: -------------------------------------------------------------------------------- 1 | # 표현 계층 2 | 3 | ### 1. 표현 계층에 대해서 설명해주세요. 4 | * 표현 계층은 코드 간의 번역을 담당하여 응용 계층에서 사용자와 시스템에서 데이터의 형식 상 차이를 다루는 부담을 줄여줍니다. **인코딩, 암호화, 압축**등이 표현 계층에서 이루어집니다. 5 | 6 | ### 2. 표현 계층에서 사용하는 인코딩 방식을 설명해주세요. 7 | * 대표적으로 MIME(Multipurpose Internet Mail Extensions) 인코딩이 있습니다. MIME 인코딩은 바이너리 파일을 텍스트 파일로 변환하는 인코딩을 말합니다. -------------------------------------------------------------------------------- /Network/REST API.md: -------------------------------------------------------------------------------- 1 | # REST API 2 | 3 | - 애플리케이션을 설계하기위한 아키텍처 스타일중 하나입니다. 4 | - 리소스를 식별하고 주소를 지정하는 방법, 클라이언트와 서버가 HTTP를 통해 통신하는 방법을 정의하는 원칙,제약조건입니다. 5 | - 리소스와 액션(HTTP 메서드)로 이루어집니다. 6 | 7 | 8 | ### Q) REST API의 특징, 장점 9 | 10 | - 상태를 저장하지 않는 방식이기때문에 서버와 클라이언트가 독립적으로 발전할수있다. 11 | 12 | - 상태를 저장하지 않기때문에 많은수의 동시요청을 받아들일수있고 확장성에 유리하다. 13 | 14 | - 상대적으로 직관적이고 쉬운 방식이다. 15 | 16 | 17 | ### Q) REST API 설계 규칙 18 | 19 | - URI가 리소스를 나타내고 리소스가 식별하는 데이터를 설명해야한다 20 | 21 | - 동사대신 명사를 사용하고 복수형으로 사용한다 22 | 23 | - API응답에 링크를 포함해 HATEOAS원칙을 지키는걸 고려해야한다 24 | 25 | - 엔드포인트, 요청응답형식, 매개변수등을 문서화하여 최신문서를 유지해야한다. 26 | 27 | ### Q) put/patch 메서드로 multipart를 사용할때 REST 하게 설계할수있을까요? 28 | 29 | - 데이터+ 파일을 함께보내는 API인경우 서로 다른 리소스를 한번에 처리하기때문에 데이터형식이 명확하지못하며 데이터와 이미지 API를 분리해서 만드는것이 더 좋은설계라고합니다. 30 | 31 | ### Q) HTTP 메서드중 캐싱이 가능한 메서드는? 32 | 33 | - 일반적으로 GET 메서드에대해 캐싱하는것으로 제한한다. 34 | 35 | ### Q) REST 서버는 계층화 되어있다고 볼수있나요? 36 | 37 | - 클라이언트는 REST API 서버만 호출하고 API서버는 비즈니스 루직만 수행합니다. API 서버는 서버 앞단에 보안,로드밸런싱, 암호화 등을 추가할수있어 계층화될수있다고 볼수있습니다. 38 | -------------------------------------------------------------------------------- /Network/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Network/SessionLayer.md: -------------------------------------------------------------------------------- 1 | # 세션 계층 2 | 3 | ### 1. 세션 계층에 대해서 설명해주세요. 4 | 5 | * 세션 계층은 양 끝단의 응용 프로세스가 통신을 관리하기 위한 방법을 제공해주고, 네트워크 상 양쪽 연결을 지속시켜주는 역할을 합니다. 6 | * 통신을 하기 위해 전이중통신 혹은 반이중통신 같은 전달 방식도 관리를 하며, TCP/IP 세션을 만들고 유지하며 세션이 종료되거나 전송이 중단될 시 복구를 하기 위한 동기화도 제공합니다. 7 | 8 | ### 2. 세션 계층의 동기화에 대해서 설명해주세요. 9 | ![세션계층 동기화](https://mblogthumb-phinf.pstatic.net/MjAxOTA0MjNfMjMx/MDAxNTU1OTgzNDg2NTU1.yoHsHSSuV85zupTfvyxeefdTAaq96-KdvcP9-yI99tog.8baNq2WQKtnxFcEnUiuW_DxTXzmP_y1mIAkN0pITkcgg.PNG.cni1577/%EC%BA%A1%EC%B2%98.PNG?type=w800) 10 | * 세션 계층은 **서로 간의 통신 중에 동기점을 선택해서 해당 지점까지의 데이터는 안전하게 도착했다는 것을 보장하여 동기화를 수행**한다. 주 동기점과 주 동기점 사이에는 부 동기점이 존재하는데, 주 동기점에 대하여 어디서 잘못되었는지 확인하고 내부의 부 동기점에서 재차 확인하여 거슬러 올라가면서 확인이 가능합니다. 11 | 12 | #### Q) 전이중통신과 반이중통신에 대해서 설명해주세요. 13 | 1. **전이중통신** : 전이중통신은 두 디바이스간 통신선을 송신선과 수신선 두 가지를 따로 사용하여 데이터의 송수신을 각 디바이스가 동시에 가능하도록 하는 통신 방식입니다. 14 | 2. **반이중통신** : 반이중통신은 전이중통신과 달리 두 디바이스간 통신선이 하나만 존재합니다. 송수신선을 서로가 공유중이기 때문에 한 쪽에서 송신을 하는 도중에 다른 쪽에서 송신을 하게 되면 충돌 문제가 발생하므로 반대쪽에서는 수신만 하도록 하는 통신 방식입니다. 15 | 16 | ### 3. 세션 하이재킹에 대해서 설명해주세요. 17 | ![세션 하이재킹](https://postfiles.pstatic.net/MjAxNzEwMTBfMjA4/MDAxNTA3NjQwNzQyNDk5.EUY9CqxhBp5k3OeJIovWoZCtXpjnGnX34vtapNcmH9Mg.MhB8H2gWVv-siQeeJb1DegV0sDEYrzekxcGR4Bt3un8g.PNG.wnrjsxo/image.png?type=w773) 18 | * 세션이랑 두 호스트가 연결이 된 상태를 의미합니다. 여기서 세션 하이재킹이란 이 연결이 활성화 된 상태를 가로채는 것을 말합니다. 19 | * 세션 하이재킹은 TCP/IP 연결에서 발생하는 취약점을 이용한 공격입니다. 20 | * TCP/IP 연결 시에 취약점은 TCP/IP는 3-way-handShake를 하는 과정에서 클라이언트와 서버가 각각 SequenceNumber와 Acknowledgment Number를 주고 받으면서 받아야 하는 데이터인지 확인을 합니다. 만약에 문제가 있다면 이를 바로 잡기 위해 재수행을 하는데 이러한 점을 공격자는 이러한 점을 악용하여 클라이언트와 서버에게 각각 잘못된 시퀀스 넘버를 위조하여 제공하고, 스니핑을 통해 SequenceNumber를 알아낸 뒤 바로 잡는 동안 공격자가 세션을 가로채서 전송을 하는 방식입니다. 21 | 22 | 23 | ### 참고자료 주소 24 | - https://m.blog.naver.com/cni1577/221520444328 25 | - https://hydroponicglass.tistory.com/280 26 | - https://blog.naver.com/PostView.nhn?blogId=wnrjsxo&logNo=221114275533&parentCategoryNo=&categoryNo=2&viewDate=&isShowPopularPosts=true&from=search -------------------------------------------------------------------------------- /Network/TCP, UDP.md: -------------------------------------------------------------------------------- 1 | # TCP, UDP 2 | 둘 다 데이터를 보내기 위해 사용하는 프로토콜 입니다. 3 | TCP 는 연결형 서비스로, 속도는 느리지만 신뢰성이 높습니다. 4 | UDP 는 비연결형 서비스, 속도는 빠르지만 신뢰성이 낮습니다. 5 | 6 | ### Q) HTTP에서 꼭 TCP를 연결해서 사용해야하는 이유? 7 | - 신뢰성을 보장하기 위해서 입니다. 8 | - HTTPS 를 사용하면 SSL/TLS 와 함께 사용할 수 있다는 이점이 있습니다. 9 | 10 | ### Q) TCP는 신뢰성을 보장하고 오류를 검출하는데, 어떤 방식으로 오류를 검출할까요? 11 | > 💡Hint) TCP 의 헤더에 담긴 정보 중 하나 12 | 13 | checkSum을 통해 오류를 검출합니다. 14 | - 체크섬은 전송할 데이터를 16bits씩 나눠서 차례대로 더해가는 방법으로 생성합니다. 15 | - 두 개의 수를 더했을 때 자리 수가 하나 올라간 부분을 캐리(Carry)- 계산 결과에서 캐리 부분만 떼어내서 다시 계산 결과에 더함.(Warp Around) 16 | - 마지막 계산 결과에 1의 보수를 취하면 => 체크섬 17 | 18 | - 수신 측은 데이터를 받으면 위의 과정을 동일하게 거치되 1의 보수를 취하지 않은 값까지만 만든 다음, 이 값과 송신 측이 보낸 체크섬과 XOR 연산을 통해 모든 비트가 1이라면 이 데이터가 정상이라고 판단합니다. 19 | 20 | - 0이 하나라도 있으면 송신 측이 보낸 데이터에 뭔가 변조가 있었음을 알 수 있음 ! 21 | 22 | ### Q) TCP는 SYNC 와 ACK 를 통해 연결을 수립하고, 반환하는 방식에 대해 설명해주세요. 23 | **3-way-HandShaking (연결 과정)** 24 | 25 | 1. 클라이언트가 서버에게 SYN 패킷을 보냄 (sequence : x) 26 | 2. 서버가 SYN(x)을 받고, 클라이언트로 받았다는 신호인 ACK와 SYN 패킷을 보냄 (sequence : y, ACK : x + 1) 27 | 3. 클라이언트는 서버의 응답은 ACK(x+1)와 SYN(y) 패킷을 받고, ACK(y+1)를 서버로 보냄 28 | 29 | **4-way-HandShaking (반환 과정)** 30 | 31 | 1. 클라이언트는 서버에게 연결을 종료한다는 FIN 플래그를 보냄 32 | 2. 서버는 FIN을 받고, 확인했다는 ACK를 클라이언트에게 보냄 (이때 모든 데이터를 보내기 위해 CLOSE_WAIT 상태가 된다) 33 | 3. 데이터를 모두 보냈다면, 연결이 종료되었다는 FIN 플래그를 클라이언트에게 보냄 34 | 4. 클라이언트는 FIN을 받고, 확인했다는 ACK를 서버에게 보냄 (아직 서버로부터 받지 못한 데이터가 있을 수 있으므로 TIME_WAIT을 통해 기다림) 35 | - 서버는 ACK를 받은 이후 소켓을 닫는다 (Closed) 36 | - TIME_WAIT 시간이 끝나면 클라이언트도 닫는다 (Closed) 37 | 38 | ### Q-1) 4-way에서 TIME_WAIT 용어와 필요성에 대해 설명해주세요. 39 | - 전송 중에 지연되어 연결이 닫힌 후 도착하는 패킷이 있을 수 있으므로 TIME_WAIT 상태가 필요합니다. ACK 세그먼트를 수신한 후 소켓이 즉시 닫히면 이러한 지연된 패킷이 손실되어 데이터가 손실되거나 손상될 수 있습니다. 40 | 41 | ### Q) 3-way-HandShaking 이전에 사용했던 2-way-HandShaking가 있습니다. 이제 사용하지 않는 이유는 뭘까요? 42 | - 마지막 단계가 빠져 2-way가 된다면 클라이언트가 ACK를 받았는 지 알 수 없습니다. 따라 2-way는 신뢰성을 보장할 수 없습니다. 43 | 44 | ### Q) 지금까지 클라어인트와 서버로 설명하셨는데, 웹서버가 클라이언트가 될 수 있을까요? 45 | - 네 가능합니다. 46 | ### Q-1) 그럼 클라이언트와 서버의 관계를 설명해주세요. 47 | - 클라이언트 : 데이터를 요청하는 쪽 48 | - 서버 : 요청한 데이터를 반환하는 쪽 49 | 50 | ### Q-2) 각각의 클라이언트끼리 Syn 패킷을 보내면 어떻게 될까요? 51 | > ❌ 오답 : 패킷 충돌 52 | - TCP는 전이중 방식을 취하기 때문에, 각 클라이언트는 독립적으로 TCP연결을 유지합니다. SYN packet에 대한 파이프가 따로 생성됩니다. 53 | 54 | ### Q-3) SYN bit를 보낼 때 발생할 수 있는 취약점에 대해 설명해주세요. 55 | - Backlog Queue는 서버가 클라이언트의 연결 요청을 대기할 때, 요청 정보를 저장하는 공간입니다. 만약 정상 연결 되었다면(ESTABLISHED) Backlog Queue 공간에서 연결 요청정보가 삭제되어 공간은 계속 유지됩니다. 하지만 연결 과정이 중간에 정상적으로 진행되지 않는다면 정보가 계속 Backlog Queue에 남아있게 됩니다. 56 | - 계속 연결요청 대기 Queue가 쌓이면 Backlog Queue 공간을 가득 채워 다른 연결 요청 정보 저장이 불가합니다. 57 | - SYN 패킷이 백로그 큐에 어느 정도 저장이 되겠지만 결국 가득 차게(flooding) 되어 더 이상의 연결을 받아들일 수 없는 상태, 즉 서비스 거부 상태로 들어가게 되는 것이다. 58 | - 이처럼 백로그 큐가 가득 찼을 경우에 공격을 당한 해당 포트로만 접속이 이루어지지 않을 뿐 다른 포트에는 영향을 주지 않고, 또한 서버나 네트워크에 별다른 부하도 유발하지 않기 때문에 관리자가 잘 모르게 되는 경우가 많다. 59 | 60 | - 누군가 악의적으로 서버에게 SYN패킷을 계속 보내게 될 때, 그 과정에서 서버가 다운되거나 느려지는 Sync flooding 현상이 발생합니다. 61 | 62 | ### Q-3-1) Sync flooding 해결 방안에 대해 설명해주세요. 63 | 1. Backlog Queue의 크기를 늘린다. 64 | 2. SYN Cookie를 설정한다. 65 | 3. TCP 연결 과정 대기 시간을 줄인다. 66 | 4. 방화벽의 동일 클라이언트 IP에 대해 연결 요성(SYN) 임계치를 설정한다. 67 | 68 | ### Q) 온라인 게임이나 DNS와 같은 프로그램은 어떤 통신 프로토콜을 사용하는 지 이유와 함께 설명해주세요. 69 | - 속도가 빨라야 하기 때문에 UDP 프로토콜을 사용합니다. 70 | 71 | ### Q-1) UDP를 사용했을 때, 패킷 손실 등의 단점은 DNS 를 사용하면 위험하지 않을까요? 72 | - DNS 관련 손실은 Application layer에서 처리해줍니다. 73 | 74 | ### Q) 4-way-handShaking에서 중간에 한 쪽에서 서버를 끊어야하는 경우 어떻게 해결하나요? 75 | - Reset패킷을 사용하여 연결을 강제로 종료합니다. 76 | 77 | ### Q-1) 마지막에 서버쪽에서 FIN을 보내고 클라이언트의 ACK를 서버쪽에서 받지 못하는 경우, 어떻게 판단하나요? 78 | - TIME WAIT에 걸어둔 시간이 다 지나면 , TIME OUT 으로 연결이 종료됩니다. 79 | 80 | ### Q-2) 어플리케이션을 사용하다보면 TIME_WAIT이 길게 잡혀있습니다. 그럼 성능이 저하될 것 같은데, 이를 개선하기 위해 도입된 방법을 아시나요? 81 | > 💡Hint! 명시적 혼잡 통보, TCP 헤더의 예약 비트에 추가된 비트로 확인 82 | - 새롭게 추가된 NS, CWR, ECE 플래그는 네트워크의 명시적 혼잡통보(Explicit Congestion Notification, ECN)을 위한 플래그입니다. 83 | - CWR, ECE, ECT, CE 플래그를 사용하여 상대방에게 혼잡 상태를 알려줄 수 있는데, 이 중 CWR, ECE는 TCP 헤더에 존재하고 ECT, CE는 IP 헤더에 존재합니다. 84 | - NS : ECN에서 사용하는 CWR, ECE 필드가 실수나 악의적으로 은폐되는 경우를 방어하기 위해 RFC 3540에서 추가된 필드 85 | - ECE : ECN Echo 플래그. 해당 필드가 1이면서, SYN 플래그가 1일 때는 ECN을 사용한다고 상대방에게 알리는 의미. SYN 플래그가 0이라면 네트워크가 혼잡하니 세그먼트 윈도우의 크기를 줄여달라는 요청의 의미 86 | - CWR : 이미 ECE 플래그를 받아서, 전송하는 세그먼트 윈도우의 크기를 줄였다는 의미 87 | 88 | ### Q) TCP와 UDP의 통신방식에 대해 설명해주세요. (1:1, 1:N 등 ...) 89 | - TCP : 1:1 90 | - UDP : 1:1, 1:N, N:N 91 | 92 | ### Q) TCP와 UDP의 패킷 교환방식에 대해 설명해주세요 (가상 회선 방식, 데이터그램 방식) 93 | - TCP : 가상 회선 방식 94 | - UDP : 데이터그램 방식 95 | 96 | ### Q) TCP와 UDP는 checkSum 프로토콜을 다른 방식으로 검사하는데, 그 방식에 대해 설명해주세요. 97 | 98 | TCP와 UDP 모두 데이터 무결성을 보장하기 위해 체크섬 프로토콜을 사용하지만, TCP의 알고리즘은 더 복잡합니다. 99 | 100 | TCP : Checksum 필수, 데이터를 송신하는 중에 발생할 수 있는 오류를 검출하기 위한 값 101 | - 전체 TCP 세그먼트를 대상으로 계산합니다. 102 | - 복잡한 알고리즘이 사용되어 TCP 헤더 및 페이로드 데이터를 모두 포함하는 16비트 체크섬 값이 TCP 헤더에 추가됩니다. 103 | 104 | ![image](https://user-images.githubusercontent.com/67494004/236833547-6b18f080-e557-4099-ae4e-9886b7125062.png) 105 | UDP : Checksum 선택, 네트워크를 통해서 전송된 데이터의 값이 변경되었는지(무결성)를 검사하는 단순한 값 106 | - 체크섬을 UDP 헤더 및 페이로드 데이터에 대해서만 계산하며 IP 헤더는 제외 107 | - TCP보다 더 간단한 알고리즘이 사용되어 16비트 체크섬 값이 UDP 헤더에 추가됩니다. 108 | 109 | ### Q) TCP에서 흐름제어, 혼잡제어에 대해 설명해주세요. 110 | **흐름제어** 111 | - 송신자측 속도가 빠를 경우, 수신자측 버퍼가 다 찼을 때 데이터 손실이 발생합니다. 이를 방지하기 위해 흐름제어를 사용합니다. 112 | 113 | **혼잡제어** 114 | - 라우터가 값을 못받을 때 계속 재전송을 하게 되는데, 이 때 네트워크가 혼잡해짐 115 | 네트워크 내의 패킷 수가 과도하게 생성될 때 혼잡이 발생하고, 이를 방지하기 위해 혼잡 제어 116 | 117 | ### Q-1) 혼잡제어 방식에 대해 설명해주세요. 118 | **AIMD(Additive Increase / Multicative Decrease)** 119 | 120 | 121 | - 송신 측이 transmission rate(window size)를 패킷 손실이 일어날 때까지 증가시키는 방식입니다. 122 | - additive increase : 송신 측의 window size를 손실을 감지할때까지 매 RTT 마다 1 MSS씩 증가시킨다. 123 | - multiplicative decrease : 손실을 감지했다면 송신측의 window size를 절반으로 감소시킨다. 124 | - 단점 : AIMD는 window size를 1MSS씩 밖에 증가시키지 않기 때문에 네트워크의 모든 대역을 활용하여 빠른 속도로 통신하기까지 시간이 오래 걸립니다. 125 | 126 | **Slow Start (느린 시작)** 127 | 128 | 129 | - 송신 측이 window size를 1부터 패킷 손실이 일어날 때까지 지수승(exponentially)으로 증가시키는 방식입니다. 130 | - 초기 window size : 1 MSS 131 | - 매 RTT마다 window size를 2배로 키움 ( ex : 1, 2, 4, 8, 16...) 132 | - 패킷 손실을 감지하면 window size를 1 MSS로 줄임. 133 | - 처음에는 window size가 1이라 속도가 느리나 지수승으로 window size가 커지므로 속도도 빠르게 증가합니다. 134 | 135 | ### +) TCP 혼잡 제어 정책 136 | **TCP Tahoe** 137 | 138 | - 처음에는 Slow Start를 사용하다가 임계점(Threshold)에 도달하면 AIMD 방식을 사용 139 | - 처음 window size는 1 MSS 140 | - 임계점까지는 Slow Start를 사용한다( window size가 2배씩 증가) 141 | - 임계점부터는 AIMD 방식을 사용한다( window size가 1씩 증가) 142 | - 3 duplicate ACKs 혹은 timeout을 만나면 아래와 같이 줄임. 143 | - 임계점 : window size의 절반 144 | - window size : 1 145 | - TCP Tahoe 방식은 3 duplicate ACKs를 만나고 window size가 다시 1부터 키워나가야 하므로 속도가 느립니다. 146 | 147 | **TCP Reno** 148 | 149 | - TCP Tahoe와 비슷하지만 3 dupicate ACKs와 timeout을 구분한다는 점이 다릅니다. 150 | - 처음 window size는 1 MSS 151 | - 임계점까지는 Slow Start를 사용 (window size가 2배씩 증가) 152 | - 임계점부터는 AIMD 방식 사용( window size가 1씩 증가) 153 | - 3 duplicate ACKs를 만나면 154 | - window size를 절반으로 줄이고 임계점을 그 값으로 설정 155 | - timeout을 만나면 156 | - window size를 1로 줄인다. 임계점은 변하지 않는다. 157 | 158 | 159 | ### Q-2) 흐름제어에서 대표적인 해결방안 STOP AND WAIT, SLINDING WINDOW 에 대해 설명해주세요. 추가로 SLINDING WINDOW는 STOP AND WAIT의 단점을 보완하기 위해 나온건데 그 이유도 함께 설명해주세요. 160 | **STOP AND WAIT** 161 | ![image](https://user-images.githubusercontent.com/67494004/236832901-69754e89-f053-48f7-8cf9-a996898f6699.png) 162 | - 매번 전송한 패킷에 대해 확인 응답을 받아야만 그 다음 패킷을 전송하는 방법 163 | 164 | **SLINDING WINDOW** 165 | ![image](https://user-images.githubusercontent.com/67494004/236832941-23e3318b-b5ee-4df3-b459-46c32337a3ad.png) 166 | - 수신측에서 설정한 윈도우 크기만큼 송신측에서 확인응답없이 세그먼트를 전송할 수 있게 하여 데이터 흐름을 동적으로 조절하는 제어기법 167 | - 먼저 윈도우에 포함되는 모든 패킷을 전송하고, 그 패킷들의 전달이 확인되는대로 이 윈도우를 옆으로 옮김으로써 그 다음 패킷들을 전송합니다. 168 | - 최초 윈도의 크기는 3way-handshaking 과정을 통해 설정 169 | - 이후 수신측에서 버퍼의 공간에 따라 변경합니다. ('윈도우'값은 TCP header에 존재하고 관리됩니다.) 170 | - 윈도우에 포함된만큼은 수신 측의 응답(ACK)없이도 보낼 수 있지만, 그 이상은 보낼 수 없습니다. 171 | - 그 이상의 데이터 패킷을 보내기 위해서는 수신의 응답(ACK)가 확인되어 다시 윈도우의 크기가 갱신되어야 합니다. 172 | 173 | 174 | 175 | 176 | ### 참고 177 | [TCP 혼잡제어](https://code-lab1.tistory.com/30) 178 | [내용 및 사진 - 1](https://evan-moon.github.io/2019/10/08/what-is-http3/) 179 | -------------------------------------------------------------------------------- /Network/TransportLayer.md: -------------------------------------------------------------------------------- 1 | # 전송 계층 2 | 3 | ### 1. 전송 계층에 대해서 설명해주세요. 4 | 5 | * 전송 계층은 **네트워크의 구성요소와 프로토콜 내에서 송신자와 수신자를 연결하는 통신 서비스를 제공하는 계층**이다. end to end간의 데이터 전송을 담당한다. 6 | 데이터 링크와 다른 점은 데이터 링크는 물리적인 연결에 대한 얘기이지만, 전송 계층은 논리적인 연결에 대한 프로세스간 통신을 담당한다. 7 | * 주된 프로토콜로 **연결형 통신에 사용되는 TCP**와 **비연결형 통신에 사용되는 UDP**가 있고, 8 | **TCP는 신뢰성있고 정확한 데이터를 전달하기 위한 프로토콜**이다. 9 | **UDP는 데이터가 빠르게 전송되는 것을 목적으로 하고 있는 프로토콜**이다. 10 | 11 | ### 1. TCP 프로토콜과, UDP 프로토콜에 대하여 각자 다른 프로토콜을 사용하고, 이 과정에서 포트가 같다면 같은 것으로 인식하나요? 12 | 13 | * 애플리케이션 계층에서 URL을 인식할 때 아래와 같이 인식합니다. 14 | * scheme://[userInfo:Password@]host[:port][/path][?query][#fragment] 15 | * 기본적으로 **[ ]는 생략이 가능** 16 | * `scheme` : 서비스의 종류, 프로토콜 정보 17 | * `://` : 뒤에 이어지는 문자열이 서버주소임을 나타냄 18 | * `userInfo` : 사용자명 19 | * `password` : 패스워드 20 | * `host` : 도메인 (서버 주소) 21 | * `:port` : 포트 번호 22 | * `/path` : 경로 23 | * `?query` : Query String, Query Parameter 24 | * `#Fragment` : 내부 북마크 25 | * scheme 조건에 따라서 **TCP를 사용하는 프로토콜과 UDP를 사용하는 프로토콜이 대부분 다르므로 다르다고 인식합니다.** 26 | 27 | ### 2. 전송계층에서 TCP 헤더를 데이터에 붙였을 때, UDP 헤더를 데이터에 붙였을 때 부르는 데이터의 이름을 말해주세요. 28 | * TCP 헤더를 붙였을 때는 **세그먼트** 라고 부릅니다. 29 | * UDP 헤더를 붙였을 때는 **UDP 데이터그램** 이라고 부릅니다. 30 | 31 | ### 3. TCP는 멀티캐스팅과 브로드캐스팅을 지원하는가 32 | * TCP는 서로 간의 신뢰성있는 통신이 목적이기 때문에 멀티캐스팅과 브로드캐스팅을 사용하지 않습니다. 33 | 34 | ### 4. UDP 프로토콜 위에서 실시간 서비스 제공 시 더 빠르고 안정성있게 제공하기 위해 사용하는 프로토콜에 대해서 설명해주세요. 35 | * RTP(Real-time Transport Protocal)는 실시간 음성과 영상 및 데이터를 IP 네트워크로 전송하는 표준 프로토콜입니다. 36 | * 추가적으로 RTP는 RTCP를 이용하여 데이터의 전달 상황을 감시 및 최소한의 제어 기능과 미디어 식별등을 제공하고 있고, RTP가 RTCP를 사용하는 것은 옵션입니다. 37 | * 데이터를 안정성있게 제공하기 위하여 RTP는 내부적으로 Timestamp(발송 시간)을 사용하여 수신측에서 재정렬하도록 해줍니다. 38 | 39 | 40 | ### 참고자료 주소 41 | - https://velog.io/@pjh612/OSI-7%EA%B3%84%EC%B8%B5-%EC%A0%84%EC%86%A1-%EA%B3%84%EC%B8%B5 -------------------------------------------------------------------------------- /Network/웹 접속 과정.md: -------------------------------------------------------------------------------- 1 | # 브라우저에 google 을 검색했을 때 일어나는 일 2 | 3 | 1. 브라우저창에 google.com을 치면 DNS에서 IP주소를 찾습니다. 4 | 2. IP주소로 TCP연결을 수립합니다.(3-way-handShaking) 5 | 3. Http Request 를 작성해 서버로 전송합니다. 6 | - OS의 프로토콜 스택에 메세지 전송 의뢰 7 | - 프로토콜 스택이 LAN에 제어정보를 붙인 패킷을 LAN 어댑터에 넘김 8 | - LAN 어댑터는 이것을 전기신호로 변환시켜 LAN 케이블로 송출 9 | - 송신한 패킷은 허브, 스위치, 라우터를 공유하여 프로바이더에 전달 10 | - 패킷은 수많은 액세스 회선을 통해 POP를 거쳐 인터넷 핵심부에 들어감 11 | - 많은 고속 라우터들 사이로 패킷이 상대방 서버까지 도달 12 | <서버> 13 | - 서버측의 LAN에 도착하면 방화벽이 패킷을 검사함 14 | - 이상없을 경우 캐시 서버가 먼저 응답 데이터 있는 지 확인 15 | 4. 서버는 Http Response를 작성해 보냅니다. 16 | 5. 받은 응답으로 웹 화면을 그립니다. 17 | 18 | ### Q) google 이라는 도메인명 IP주소를 조회할 때, 찾는 과정에 대해 설명해주세요. 19 | - DNS 내에서 Top-level -> Second-level -> Sub-level 순으로 검색합니다. 20 | ![image](https://github.com/kim-se-jin/CS-JAVA-Study/assets/67494004/4953e751-52d9-486e-9293-414e96049632) 21 | - 최초의 Root 네임 서버의 IP 주소에게 [www.naver.com을](http://www.naver.xn--com-of0o/) 물어보면 22 | - .com을 담당하는 Top-level을 알려주고, 23 | - Top-level은 naver.com을 담당하는 Second-level을 알려주고, 24 | - Second-level은 [www.naver.com을](http://www.naver.xn--com-of0o/) 담당하는 sub DNS Server에게 물어보며 sub가 해당 IP 주소를 알려주는 것 25 | 26 | - 각각의 부분들을 담당하는 독자적인 Server Computer가 존재하여, 상위 목록이 직속 하위 목록을 알고 있습니다. 27 | - Root는 Top-level을 담당하는 Server 목록과 IP를 알고 있으며, 28 | - Top-level은 Second-level의 Server 목록과 IP를 알고 있고, 29 | - Second-level은 sub 목록과 IP를 알고 있음. 30 | 31 | ### Q-1) DNS에 찾기 전에 있는 과정에 대해 아시나요? 32 | - hosts 파일의 캐시를 확인합니다. 33 | - hosts파일은 운영체제 내부에 위치하며, 각각의 도메인네임과 이들의 IP주소를 하나하나 대응시켜서 저장해 놓은 텍스트파일입니다. 34 | 35 | ##### +) 이렇게 캐싱되는 이유 36 | - 네트워크 트레픽을 조절하고 데이터 전송 시간을 줄이기 위해 37 | 38 | ### Q) 내가 사용하는 DNS서버를 어떻게 정하나요? 39 | > Hint ! DHCP 40 | - DHCP, 동적 호스트 설정 프로토콜(Dynamic Host Configuration Protocol) 로 찾습니다. 41 | - IP주소, 서브넷 마스크, 기본게이트웨이 IP주소, DNS서버 IP주소 를 자동으로 일정 시간 할당해주는 인터넷 프로토콜입니다. 42 | 43 | - DNS서버에 네임서버를 요청하기 전, 거리가 가까운 DNS라우터를 찾습니다. DHCP로 제일 가까운 DNS라우터를 찾아와 외부와 통신할 준비를 마치고, 정해진 DNS서버에 네임서버 요청하게 됩니다. 44 | 45 | +) ARP를 통해 IP주소와 가장 가까운 네임서버 46 | - 실질적인 통신을 하기 위해서는 논리 주소인 IP주소를 물리 주소인 MAC 주소로 변환해야 합니다. 이를 위해 해당 네트워크 내에서 ARP를 브로드 캐스팅합니다. 해당 IP주소를 가지고 있는 노드는 자신의 MAC 주소를 응답합니다. 47 | 48 | ### Q) 가장 가까운 주소를 찾았는데, 물리적으로 먼 서버에 어떻게 접속하는 지 설명해주세요. (한국 -> 미국 접속 과정) 49 | - 많은 고속 라우터들 사이를 지나 패킷이 상대방 서버까지 도달하게 됩니다. 50 | 51 | ### Q-1) URI, URL, URN 차이 52 | - URI (Uniform Resource Identifier) : 인터넷 상의 자원을 식별하기 위한 문자열의 구성 53 | - URL과 URN을 포함 54 | - URL (Uniform Resource Locator) : 인터넷 상 자원의 위치 55 | - ex) https://www.google.com:443/search?q=hello&hi=ko 56 | - URN : 자원의 이름 57 | - ex) ex: urn:something:names:somehitng... 58 | 59 | ### Q-2) URN을 사용하지 않고, URL을 사용할까요? 60 | - URN은 자원에 부여된 고유한 이름 그 자체로, 자원의 위치를 찾을 수 없습니다. 하지만, URL은 인터넷 상의 자원을 식별하고 위치를 제공할 수 있기 때문에 실용적입니다. 61 | 62 | ### Q) IP주소를 찾아온 후에 TCP연결 과정에서 만약 서버의 위치가 외국인 경우, 거리가 멀수록 효율적이지 않습니다. 극복하기 위해 사용하는 방법에 대해 아시나요? 63 | - CDN 입니다. Content Delivery Network의 약자로 지리적인 제약 없이 전 세계 사용자에게 빠르고 안전하게 컨텐츠 전송을 할 수 있는 기술을 말합니다. 이를 통해서 컨텐츠의 병목현상을 피할 수 있습니다. 64 | - 서버를 분산시켜 캐싱해두고 사용자의 컨텐츠 요청이 들어오면 사용자와 가장 가까운 위치에 존재하는 서버로 매핑시켜 요청된 콘텐츠의 캐싱된 내용을 내어주는 방식으로 빠르게 데이터를 전송할 수 있습니다. 65 | ![image](https://github.com/kim-se-jin/CS-JAVA-Study/assets/67494004/18a042c1-6842-4da5-a1d7-46d0cc9b6085) 66 | 67 | 왼쪽 : CDN을 사용하지 않을 경우, 오른쪽 : CDN을 사용할 경우 68 | - 만약 서버가 파일을 찾는데 실패하는 경우 CDN 플랫폼의 다른 서버에서 컨텐츠를 찾은다음 응답을 전송 69 | 70 | ### Q-1) 추가로 GSLB 에 대해 아시나요? 71 | - GSLB(Global Server Load Balancing)란, DNS 기반의 로드밸런싱 서비스입니다. 72 | - 재난 복구, 부하 분산, 성능 등의 기능이 있습니다. 73 | - 재난 복구 (disaster recovery) 74 | - 실패에 대해 대체할 수 있는 서버를 제공합니다. 75 | - 부하 분산 (load sharing) 76 | - 많은 트래픽을 여러 서버로 분산합니다. 77 | - 성능 (performance) 78 | - client의 위치나 네트워크를 기반으로 최적의 성능을 낼 서버를 선택합니다. 79 | 스크린샷 2023-05-14 오후 1.47.47.png 80 | - 대표적인 서비스 81 | AWS : Route53 82 | Google Cloud : Cloud Load Balancing 83 | Azure : Traffic Manager 84 | Naver : Global Route Manager 85 | F5 86 | Citrix 87 | 88 | 89 | ### Q) 웹 서버 주소에 IP주소를 알았을 때, HTTP request를 합니다. 이 과정에서 TCP/IP 기반이라고 할 때 어떤 과정이 일어날까요? 90 | - 3-way-handShaking 입니다. 91 | 92 | ### Q) DNS에서 로드밸런싱을 위해 라운드로빈 방식을 사용하는데, 왜 사용할까요? 93 | - 시간단위로 특정 서버에 몰아주며 균등하게 유저들을 배포합니다. 94 | - 웹 사이트에 접속을 원하는 사용자가 해당 도메인 주소를 브라우저에 입력하면, DNS는 도메인의 정보를 조회하는데, 이때 IP 주소를 여러 대의 서버 IP 리스트 중에서 라운드 로빈 형태로 랜덤하게 하나 혹은 여러개를 선택하여 다시 사용자에게 알려줍니다. 95 | ![image](https://github.com/kim-se-jin/CS-JAVA-Study/assets/67494004/d27ad712-ee48-4020-ba75-c5a43beb0718) 96 | 97 | - 장점 : 중간 장비(로드밸런서 등) 없이도 서비스가 가능, 간편 98 | - 단점 99 | - 서버의 수 만큼 공인 IP 주소가 필요 100 | - 서버에 장애가 발생해도 감지하지 않고 부하를 분산시킴 101 | - 일반적인 로드밸런싱은 Health check를 수반한다. 라운드 로빈 DNS는 별도로 Health check를 하지 않음 (서버가 다운되도 확인이 불가능) 102 | - DNS 결과를 Caching해서 재사용하기 때문에 균등한 분산이 어려움 103 | - 모바일 사이트 등에서 문제가 될 수 있는데, 스마트폰의 접속은 캐리어 게이트웨이 라고 하는 프록시 서버를 경유 합니다. 104 | - 프록시 서버에서는 이름변환 결과가 일정 시간 동안 캐싱되므로 같은 프록시 서버를 경유 하는 접속은 항상 같은 서버로 접속됩니다. 105 | - 또한 PC 용 웹 브라우저도 DNS 질의 결과를 캐싱하기 때문에 균등하게 부하분산 되지 않습니다. 106 | - DNS 레코드의 TTL 값을 짧게 설정함으로써 어느 정도 해소가 되지만, TTL 에 따라 캐시를 해제하는 것은 아니므로 반드시 주의가 필요 107 | 108 | ### Q-1) 라운드로빈의 단점을 극복하기 위한 방법은 뭐가 있을까요? 109 | - 다중화 구성 방식 (Synchronous Time-Division Multiplexing) 110 | - AP 서버에 VIP(Virtual IP)를 부여해서 다중화를 구성한다. 각 AP 서버를 Health Check후 이상이 감지되면 VIP를 정상 AP 서버로 인계하는 방식을 사용한다. 111 | - 즉 DNS Server Table 에 실시간으로 AP 서버의 상태를 확인할 수 있는 칼럼 및 함수를 추가하여 요청될 경우 서버 상태를 확인하여 우회루트를 제공하거나 에러를 전송하는 방식을 말합니다. 112 | 113 | - 가중치 편성 방식 (Weighted round robin) 114 | - 각각의 웹 서버에 가중치를 가미해서 분산 비율을 변경한다. 물론 가중치가 큰 서버일수록 빈번하게 선택되므로 처리능력이 높은 서버는 가중치를 높게 설정하는 것이 좋다. 115 | 116 | 또 다른 방법으로는 로드 밸런서의 도입을 통하여 다음과 같은 구성도 가능합니다. 117 | 118 | - 최소 연결 방식 (Least connection) 119 | - 접속 클라이언트 수가 가장 적은 서버를 선택한다. 로드밸런서에서 실시간으로 connection 수를 관리하거나 각 서버에서 주기적으로 알려주는 것이 필요하다. 120 | 121 | 122 | ### Q) 같은 도메인 주소에 포트번호를 다르게 접속할 때, DNS는 같다고 판단하나요? 123 | - 아닙니다. 어떤 포트로 요청할 것인 지 분석하기 때문에, 포트가 잘못된 포트로 들어오면 다른걸로 인식합니다. 124 | - 명시적으로 포트를 선언하지 않았다면 브라우저에서는 설정된 기본값을 이용해 요청하게 됩니다. HTTP라면 80 포트를, HTTPS라면 443 포트를 기본 값으로 요청 125 | 126 | ### Q) 443포트로 https 사용하는데, 80포트로 http 로 접근할 때 어떻게 되나요? 127 | - HSTS(HTTP Strict transport security), HTTP를 허용하지 않고 HTTPS를 사용하는 연결만 허용하는 기능입니다. 만약 HTTP로 요청이 왔다면 HTTP 응답 헤더에 "Strict Transport Security"라는 필드를 포함하여 응답하고 이를 확인한 브라우저는 해당 서버에 요청할 때 HTTPS만을 통해 통신하게 됩니다. 그리고 자신의 HSTS캐시에 해당 URL을 저장하는데 이를 HSTS 목록이라고 부릅니다. 128 | 129 | - 이를 통해 브라우저에서는 이 HSTS 목록 조회를 통해 해당 요청을 HTTPS로 보낼지 판단합니다. HSTS목록에 해당 URL이 존재한다면 명시적으로 HTTP를 통해 요청한다 해도 브라우저가 이를 HTTPS로 요청합니다. 130 | 131 | -------------------------------------------------------------------------------- /Network/웹서버, WAS.md: -------------------------------------------------------------------------------- 1 | # Web Sever, Web Application Server 2 | 3 | - 웹 서버와 웹 애플리케이션 서버의 차이를 이해하기 전에 정적페이지와 동적페이지를 먼저 이해해야 한다. 4 | 5 | **정적 페이지(Static Page)** 6 | - 데이터베이스에서 정보를 가져오거나 별도의 서버에서의 처리가 없어도, 사용자에게 보여줄 수 있는 페이지 7 | - 어떠한 사용자가 요청하던 간에 동일한 페이지를 보여준다. 8 | - Ex) image, html, css, javascript 등등 9 | 10 | **동적 페이지(Dynamic Page)** 11 | - 서버에서 일련의 과정들을 거쳐서 데이터가 변할 수 있는 페이지. 12 | - 주로 데이터를 요청하여 데이터베이스에서 데이터를 받아 보여주는 페이지들이다. 13 | - 사용자가 누구인지에 따라 다른 페이지를 보여줄 수가 있다. 14 | 15 | ### 웹 서버(Web Server)와 웹 애플리케이션 서버(Web Application Server)의 차이 16 | 17 | **웹 서버(Web Server)** 18 | ![Image](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEl7zX%2FbtseSB6pu9J%2FieqUmLPXsm2KZ5jINbxefK%2Fimg.png) 19 | 1. **정적인 컨텐츠를 제공하고, WAS를 거치지 않고 자원을 바로 전달**한다. 20 | 2. 동적인 컨텐츠라면 **WAS에 전달하고, WAS가 처리한 결과를 받아서 클라이언트에게 응답 메시지를 전송**한다. 21 | 3. 아파치에서는 부가적인 기능으로 **CGI(Common Gateway Interface)** 를 제공하여 **웹 서버와 외부 프로그램 사이에서 정보를 주고 받을 수 있습니다.** 단, PHP, Perl, Python 에서만 가능하며 JAVA는 안됩니다. 22 | - EX) Apache, Nginx, IIS 23 | 24 | **웹 애플리케이션 서버(Web Application Server, WAS)** 25 | ![Image](https://blog.kakaocdn.net/dn/dzROHQ/btrinP7Hryy/s0OadohZFwNMwbVqVXhGI1/img.png) 26 | - 웹 서버로부터 오는 동적인 요청을 처리하는 서버, 웹 서버와 컨테이너를 붙여놓은 서버이다. 27 | 28 | ### Q) 웹 서버와 WAS가 어떤 차이로 각각 따로 존재해야하는지 설명해주세요. 29 | - WAS는 웹 서버가 수행하는 기능을 같이 제공해 줄 수 있습니다. 그럼에도 불구하고 웹 서버가 필요한 이유는 WAS가 처리하는 일 중에서 비즈니스 로직을 수행하는 부분은 상당히 많은 비용을 소모하게 됩니다. (DB 트랜잭션, 스레드, 예외 등) 30 | - 위의 비즈니스 로직을 수행하던 도중 큰 문제가 발생하여 WAS가 다운 될 경우, 웹 사이트에 오류가 발생했다는 정적 페이지도 뿌리지 못하고 접속 장애가 발생하는 상황이 발생합니다. 31 | - 정적 페이지를 호출하는 부분은 웹 서버에게 일임하고, 동적인 부분을 처리하는 부분을 WAS에 일임하여 각 서버들끼리에 부하를 줄이고, WAS 문제 발생 시 웹 서버가 오류 페이지를 띄울 수 있도록 할 수 있습니다. 32 | ![Image](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLpezI%2FbtseRiGiF6z%2FDNNqVsgGrbo3KIwKbbdvmK%2Fimg.png) 33 | - 추가적으로, 웹 서버와 WAS를 분리하게 되면 웹 서버와 WAS간의 유연한 확장 또한 가능합니다. 웹 서버의 자원이 부족하면 웹 서버를 증설하고, WAS의 자원이 부족하면 WAS를 증설하는 것입니다. 34 | 35 | ### Q) 웹 서버와 WAS 분리 시 빌드 할 때의 장점에 대해서 설명해주세요. 36 | - 정적 페이지는 주로 UI, UX 부분을 다루고 있기 때문에 잦은 수정이 일어나고 이에 따라 Build가 자주 발생 할 수 있습니다. 그러나 WAS 같은 경우 비즈니스 로직에 대해서는 수정이 정적인 페이지에 비해 잦은 편이 아닙니다. 37 | - 이렇게 서로 간의 수정되는 정도가 다른데, 웹 서버가 제공하는 정적 페이지 제공하는 기능을 WAS에게 일임하면 변경 사항을 빌드하기 위해서 변하지 않은 비교적 무거운 비즈니스 로직적인 부분을 빌드를 같이 진행해야 하고 이 부분에서 빌드를 하는데 상당한 시간적 비용이 소모됩니다. 38 | - 따라서, 분리를 했을 경우에는 이러한 시간적인 낭비를 줄일 수 있게 됩니다. 39 | 40 | ### Q) Java 프로그램으로 웹 개발을 하는 경우 직접 Socket 연결 및 요청 메시지, 응답 메시지 파싱을 하지 않아도 되는 이유에 대해서 설명해주세요. 41 | ![Image](https://doozi316.github.io/assets/images/WEB26/2.png) 42 | - WAS에는 웹 컨테이너라는 동적인 데이터를 처리해주는 공간이 있습니다. JAVA가 아닌 다른 Python과 같은 언어라면 CGI를 이용해 처리를 하게 해주는 것도 가능하지만, JAVA의 경우에는 제공이 안되므로 동일한 기능을 수행하는 서블릿이 Socket 연결, HTTP 요청 메시지 파싱, HTTP 응답 메시지 생성 등과 같은 일들을 편리하게 수행 할 수 있도록 해줍니다. 43 | 44 | ### Q) 웹 서버의 멀티 쓰레드 방식과 WAS의 멀티 쓰레드 방식 45 | - 해당 질문에 대해서는 자주 사용하는 웹 서버인 Apache와 NGINX의 관점에서 알 수 있습니다. 46 | #### Apache 47 | ![Image](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVSwLI%2FbtseTDo7Y9m%2FhUYfINulKlOQOaOewUpDhK%2Fimg.png) 48 | - 리눅스의 관점에서 하나의 프로세스도 하나의 스레드로 여긴다고 봤을 때, 하나의 스레드가 하나의 요청을 처리하는 방식, 만약 프로세스 관점에서 본다면 멀티 프로세스 단일 스레드 형식으로 요청을 처리합니다. 49 | #### NGINX 50 | ![Image](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTwD47%2FbtseSCEd3Qt%2FThNWAYOKsmaK8ILnI0u11k%2Fimg.png) 51 | - NGINX는 위처럼 Event-Driven 구조를 택함으로써 하나의 프로세스에 멀티 쓰레드를 담는 구조를 택하고 있습니다. 이렇게 웹 서버를 이용하기 위한 연결을 택하게 되면 클라이언트가 웹 서버에 대한 요청에 대한 쓰레드를 받아서 처리하면서, WAS 또한 멀티 쓰레드 방식으로 동작하여, 요청이 들어오면 WAS 프로세스를 처리하기 위한 쓰레드를 추가하면서 동작을 하게 하거나, 쓰레드 풀을 이용해서 쓰레드 들을 담아놓고 웹 서버의 요청이 들어오면 WAS가 처리하도록 수행합니다. 52 | 53 | - 따라서 둘 간의 관점에서 봤을 때, 기본적으로 WAS는 대부분 멀티 쓰레드를 지원하며 웹 서버에 대한 멀티 쓰레드는 서버에 따라 다를 수 있음을 확인 할 수 있습니다. 54 | 55 | ### Q) 웹 서버와 WAS 종류를 한 가지 씩 설명해주세요. 56 | - 웹 서버에는 NGINX가 있고, WAS에는 Tomcat이 있습니다. 57 | ### Q) 스프링 부트에서 제공해주는 WAS는 무엇일까요? 58 | - 스프링 부트는 자체적으로 Tomcat을 내장하고 있습니다. 59 | ### Q) 웹 서버는 OSI 7계층에서 어떤 계층에서 동작하는지에 대해서 설명해주세요. 60 | - 웹 서버는 웹 서버 자체도 프로그램이기 때문에 데이터 전송을 위한 Application 계층에 존재합니다. 61 | > Q) NGINX는 정적인 페이지에 대한 처리말고도 프록시 서버에 대한 역할도 수행하는데, 어떤 관점에서 수행되는지 설명해주세요. 62 | - **프록시 서버** : 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램, 프록시 서버는 크게 **Forward Proxy**와 **Reverse Proxy**로 나눌 수 있다. 63 | - **Forward Proxy** : 클라이언트가 인터넷에 직접 접근하는게 아니라 포워드 프록시 서버가 요청을 받고 인터넷에 연결하여 결과를 클라이언트에 전달해준다. 프록시 서버는 Cache를 사용하여 자주 사용하는 데이터라면 요청을 보내지 않고 캐시에서 가져올 수 있기 때문에 성능 향상이 가능하다. 64 | - **Reverse Proxy** : 클라이언트가 인터넷에 데이터를 요청하면 리버스 프록시가 이 요청을 받아 내부 서버에서 데이터를 받은 후 클라이언트에 전달한다. 내부 서버에 요청하지 않고 리버스 프록시에만 요청하면 프록시가 알아서 서버에게 데이터를 전달하기 때문에 안전하다. 추가적인 기능으로 로드 밸런싱 혹은 서버 확장등에도 유리하다. 65 | - **차이** 66 | 1. **EndPoint 관점** 67 | - Forward Proxy는 클라이언트가 요청하는 End Point가 실제 서버 도메인 68 | - Reverse Proxy는 클라이언트가 요청하는 End Point가 프록시 서버의 도메인 69 | 2. **감춰지는 대상 관점** 70 | - Forward Proxy 방식은 서버가 프록시 서버로 부터 요청을 받기 때문에 클라이언트의 정보를 알 수 없다. 71 | - Reverse Proxy 방식은 클라이언트가 프록시 서버에게 요청을 하기 때문에 서버의 정보를 알 수 없다. 72 | ### Q) 서블릿 컨테이너가 어떤 역할을 하는지 설명해주세요. 73 | - 서블릿 컨테이너는 자바에서 사용하기로 명시한 서블릿들을 보관해주어, 웹 서버와 손쉽게 통신 할 수 있도록 해주고, 소켓을 만들어 listen, aceept등의 API를 제공하여 HTTP 통신을 위한 복잡한 과정을 생략하게 해줍니다. 74 | - 서블릿의 생명 주기를 관리하며 멀티쓰레드 또한 지원을 합니다. 75 | 76 | ### Q) 서블릿의 요청에 따라서 응답을 달리 보내줄 수 있는데 어떻게 처리하는가 77 | - 서블릿에 대한 요청에서 Content-Type을 보고 해당 Content-Type에 맞게 데이터를 받게 될 때, 서블릿의 요청 헤더에 Accept가 어떤 것인지 혹은 API 규약이 어떤지에 따라 달라질 수 있습니다. 78 | 1. Accept가 text/html 이라면 ModelAndView 를 반환하거나, 구 시대적인 방법으로 직접 html을 생성해서 보내주는 방법이 있습니다. 79 | 2. Accept가 text/plain 이라면 response의 getWriter() 를 이용하여 반환이 가능합니다. 80 | 3. Accept가 text/xml 혹은 application/json 이라면 ObjectMapper를 사용하여 객체로 변환하고, ResponseEntity를 사용하여 응답이 가능합니다. 81 | 4. 이 외에도 요청에 따라 다양하게 응답이 가능합니다. 82 | - 질문의 의도는 HTTP 프로토콜에 따라 보내주는 요청에 따라 응답이 달라질 수 있다는 것. 83 | 84 | ### Q) 서버에 많은 트래픽이 발생했을 때 대처 할 수 있는 방안에 대해서 설명해주세요. 85 | - 가장 간단한 방법은 클라우드 서버를 이용하고 있다면 서버를 증설하는 것이 가장 간단한 방법입니다. 86 | - 만약 이러한 서버가 증설이 충분히 되어있음에도 불구하고 요청이 한 서버에만 몰려서 처리를 하게 되는 상황이라면 로드 밸런서를 설치하여 적절히 트래픽을 처리 할 수 있도록 하고 현재 요청을 받는 쓰레드가 부족하여 요청을 빠르게 수행 할 수 없는 상황이라면 적절하게 쓰레드 풀의 수를 늘려서 해결합니다. 87 | 88 | ### Q) 로드 밸런싱 기법에 대해서 설명해주세요. 89 | - 로드 밸런싱 기법에는 여러가지 방식이 있습니다. 서버의 능력을 고려하여 분배해야 하기 때문에 서버의 상황에 맞춰서 적절한 방법을 선택해주어야 합니다. 90 | 1. **라운드로빈 방식(Round Robin Method)** 91 | - 서버에 들어온 요청을 순서대로 돌아가며 배정하는 방식입니다. 클라이언트의 요청을 순서대로 분배하기 때문에 여러 대의 서버가 동일한 스펙을 갖고 있고, 서버와의 연결이 오래 지속되지 않는 경우에 적합합니다. 92 | 2. **가중 라운드로빈 방식(Weighted Round Robin Method)** 93 | - 각각의 서버마다 가중치를 매기고 가중치가 높은 서버에 클라이언트 요청을 우선적으로 배분합니다. 주로 서버의 트래픽 처리 능력이 상이한 경우에 사용되는 부하 분산 방식입니다. 94 | 3. **IP 해시 방식(IP Hash Method)** 95 | - 클라이언트의 IP 주소를 특정 서버로 매핑하여 요청을 처리하는 방식입니다. 사용자의 IP를 해싱해 로드를 분배하기 떄문에 사용자가 되도록 동일한 서버로 연결되는 것을 보장합니다. 96 | > 항상 동일한 서버로 연결되는 것을 보장한다고 써있었으나, DHCP를 이용 할 경우 보장 할 수 없으므로 되도록 이라는 말로 수정하였습니다. 97 | 4. **최소 연결 방식(Least Connection Method)** 98 | - 요청이 들어온 시점에 가장 적은 연결상태를 보이는 서버에 우선적으로 트래픽을 배분합니다. 세션이 길어지거나 서버에 분배된 트래픽들이 일정하지 않은 경우에 적합합니다. 99 | 5. **최소 응답 시간 방식(Least Response Time Method)** 100 | - 서버의 현재 연결 상태와 응답시간을 모두 고려하여 트래픽을 배분합니다. 가장 적은 연결 상태와 가장 짧은 응답 시간을 보이는 서버에 우선적으로 배분하는 방식입니다. 101 | 102 | ### 참고 자료 103 | [Web Server VS WAS](https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B5%AC%EC%A1%B0-%EC%A0%95%EB%A6%AC) 104 | [NGINX](https://ssdragon.tistory.com/60) 105 | [Apache VS NGINX](https://velog.io/@deannn/Apache%EC%99%80-NginX-%EB%B9%84%EA%B5%90-%EC%B0%A8%EC%9D%B4%EC%A0%90) 106 | [Forward Proxy, Reverse Proxy](https://bcp0109.tistory.com/194) 107 | [로드 밸런싱](https://tecoble.techcourse.co.kr/post/2021-11-07-load-balancing/) 108 | -------------------------------------------------------------------------------- /Operating System/CPU Sheduling.md: -------------------------------------------------------------------------------- 1 | 2 | # CPU Sheduling 3 | 4 | ### Process Sheduling 알고리즘에는 어떤 것들이 있나요? 5 | 6 | - CPU 스케줄링은 언제 어떤 프로세스에 CPU를 할당할지 결정하는 작업이라고 할 수 있으며, FCFS, SJF, 라운드로빈 등의 알고리즘들이 있습니다. 7 | 8 | #### Q) 단기, 장기 , 중기 스케줄러가 무엇인가요? 9 | 10 | - 장기스케줄러 : 11 | 12 | - **어떤 프로세스를 준비큐에 넣을지** 결정하는 일을 담당한다.(프로세스의 상태 : new -> ready) 13 | 14 | - 단기스케줄러 : 15 | 16 | - **장기스케줄러에 의해 선별된 작업중 어떤작업을 해야할지 고르는 일**을 담당한다.(프로세스의 상태 : ready -> running -> waiting -> ready) 17 | 18 | - 중기스케줄러 : 19 | 20 | - 메모리에 올라온 작업이 CPU가 감당하기힘든 상태가되어 시스템성능이 저하될수있는데 이를 해결하기위해 **적재된 프로세스의 수를 동적으로 조절하는일**을 담당한다.(프로세스의 상태 : ready-> suspended) 21 | 22 | 23 | > Q) 현재 CPU에서 장기스케줄러를 사용하고있나요? 사용하고있지않다면 그이유는 무엇인가요? 24 | 25 | - 사용하고있지않습니다. 10개의 준비된 프로세스중 메모리에 적재할수있는것이 6개라고 가정했을때 선별하는것이 장기스케줄러인데 현재는 메모리의 크기도 커지기도했고, 가상메모리 관리 덕분에 메모리가 무한인것처럼 사용할수있어 준비된 10개의 프로세스를 모두 적재할수있기 때문입니다. 26 | 27 | #### Q) 중기 스케줄러 동작방식에 대해 설명해주세요 28 | - 장기스케줄러에 의해 프로세스를 적재했는데 CPU가 감당하기 힘든상태가 되어 우선순위가 가장 낮거나 일정시간동안 활성되지않은 프로세스중 일부 메모리를 디스크의 스왑영역에 저장합니다. 이로인해 프로세스가 중지(suspended)상태가 됩니다. 장기스케줄러와 동일한이유로 현재 중기스케줄러는 사용되지않습니다. 29 | 30 | #### Q) 장기 스케줄러와 단기스케줄러의 실행속도는 얼마나 차이가 날까요? 31 | - 장기스케줄러는 수십초, 수분단위로 호출되어 단기스케줄러보다 느린속도이고 단기스케줄러는 스케줄링 알고리즘에 따라 ms이하의 시간단위로 매우빈번하게 호출되므로 수행속도가 충분히 빨라야합니다. 32 | 33 | 34 | #### Q) 선점형 / 비선점형 스케줄러는 무엇인가요? 35 | 36 | - 선점형 스케줄러 : 37 | - CPU를 선점하고있는 프로세스를 교체할수있는 스케줄링 방식 38 | 39 | - 비선점형 스케줄러 : 40 | - CPU를 선점하고있는 프로세스가 종료될때까지 교체할수없는 스케줄링 방식 41 | 42 | #### Q) 선점형 / 비선점형 알고리즘의 종류는 무엇이있나요? 43 | - 선점형 알고리즘에는 라운드로빈, 멀티레벨큐, 멀티레벨피드백큐 등이 있습니다. 44 | - 비선점형 알고리즘에는 SJF, HRN 등이 있습니다. 45 | 46 | #### Q) FCFS 알고리즘 사용시 문제되는점이 있을까요? 47 | 48 | ![image](https://user-images.githubusercontent.com/59333182/226124597-2328cdf0-e03c-4329-91cd-db06102e2cbe.png) 49 | 50 | - 위 그림과같이 작업 평균처리시간이 A=100, B=10, C=10 이 소요되는 작업이 차례로 들어온경우 작업 평균반환시간이 늦어지는 문제가있으며, convoy effect를 야기할수있습니다. 51 | 52 | #### Q) 위의 예에서 B,C같은 프로세스처럼 처리시간이 오래걸리는 작업이 먼저 도착해서 B,C가 오래기다리게 되는현상을 부르는 용어는 무엇인가요? 53 | - 호위 효과(convoy effect) 라고합니다. 짧은시간동안만 자원을 사용할 프로세스들이 자원을 오랫동안 사용하는 프로세스의 종료를 기다리는 현상을 의미합니다. 54 | 55 | 56 | #### Q) 라운드로빈은 어떤 스케줄링기법인지 말씀해주세요. 57 | - 작업마다 타임슬라이스를 할당받아 CPU를 선점하고, 타임슬라이스가 끝나면 다음작업으로 전환하는 방식으로 시분할 시스템에서 중요할수있는 응답시간을 개선할수있는 알고리즘입니다. 58 | 59 | 60 | #### Q) 그럼 라운드로빈은 왜 등장하게 된건가요? 61 | - 시분할 컴퓨터의 등장으로 시스템과 원활하게 상호작용 하기위해 스케줄링 알고리즘을 평가할때 '응답시간(작업이 도착해서 처음 스케줄될때까지의 시간 - 도착시간)'이라는 기준도 중요해지면서 효율적으로 시스템과 상호작용해 **응답시간을 개선하고 CPU시간을 공정하게 할당하기위해서** 등장했습니다. 62 | 63 | #### Q) 잔여시간이 긴 프로세스가 선점하지 못한채로 머무르게 되는 현상은 무엇인가요? 64 | - 기아상태 65 | 66 | #### Q) 라운드로빈의 타임슬라이스는 어느정도로 잡아야하나요? 67 | - 타임슬라이스가 짧을수록 작업의 응답시간은 좋아질수있지만, 너무 짧으면 context switching 비용이 전체 성능에 영향을 주게되고 타임슬라이스가 너무 길면 작업의 응답시간이 길어질수있습니다. 68 | 69 | 70 | #### Q) 일반적으로 라운드로빈시 타임슬라이스의 권장 할당량이 어느정도인지 아시나요? 71 | - 일반적으로는 작업별로 타임슬라이스 대비 context switching 비용을 따져봐야하지만 대부분 현대 운영체제들은 10~100msec로 할당합니다. 72 | 73 | 74 | #### Q) 우선순위 스케줄링에서 기아현상을 해결하기위한 방법이 어떤것이있나요? 75 | - 주기적으로 모든작업의 우선순위를 상향하는 방식이있습니다. 이렇게되면 프로세스가 굶지않는다는것을 보장받습니다. 76 | 다만 얼마나 자주 상향시킬것인지?에대해 생각해봐야합니다. 주기가 너무 크면 긴 실행시간을 가진 작업은 굶을수있고, 너무 작으면 I/O bound같은 대화형작업이 CPU를 적절하게 선점할수 없게됩니다. 77 | 78 | #### Q) 스케줄링기법중 멀티레벨 큐와 멀티레벨 피드백큐가 있는데, 둘다 아시는내용을 설명해주세요 79 | 80 | - 멀티레벨 큐 : 81 | 2개이상의 특정 스케줄링 규칙을 따르는 스케줄링 큐로 구성되는 방식입니다. 각 프로세스를 특정기준(우선순위 혹은 기타속성)에 따라 적절한 대기열에 할당합니다 멀티프로세서 환경에서 단일큐 스케줄링의 단점인 동기화문제를 고려하지않아도 되고 캐시친화적이라는 장점이있지만 일부 CPU가 유휴상태가 될수있는등 작업의 불균형문제가 있습니다. 82 | 83 | 예를들어, 2개의CPU가 작업중이고 4개의 작업이 있다고 가정할때, 아래와같습니다. 84 | 85 | ![image](https://user-images.githubusercontent.com/59333182/226152668-8b37362c-922c-4c82-9132-86e5eedf5094.png) 86 | 87 | 각 큐에서 라운드로빈을 실행한다는 가정하에 아래와 같은 스케줄을 얻을수있습니다. 88 | 89 | ![image](https://user-images.githubusercontent.com/59333182/226152791-fb44c08e-7f3e-4d3e-849f-76910e65c6f7.png) 90 | 91 | 작업 A 하나로 B와 D보다 2배의 CPU를 차지하게되며, **더 심한경우 Q0에 있는 작업들만 먼저 끝나게 되면 아래와같이 1개의 CPU가 유휴상태가 될수있습니다.** 92 | 93 | ![image](https://user-images.githubusercontent.com/59333182/226152837-94b386ad-bff0-460d-bf02-09b7e404790b.png) 94 | 95 | ![image](https://user-images.githubusercontent.com/59333182/226152849-bedbb22e-4f09-4fb5-97f6-3f6f412dfad8.png) 96 | 97 | - 멀티레벨 피드백 큐 : 98 | 2개이상의 큐로 구성되며 각각 다른우선순위가 배정되고,각 **큐에남아있는 작업을 확인해서 작업을 이동시켜서(migration) 위에서 얘기했던 작업의 불균형문제를 해소할수있는 방식**입니다. 대부분의 MLFQ들은 우선순위가 높은 큐는 보통 짧은 타임슬라이스가 주어지고, 우선순위가 낮은큐는 긴 타임슬라이스를 가지게되며, 일정주기를 가지고 **우선순위를 상향시켜 기아문제를 해결**하기도합니다. 99 | 100 | **둘의 가장 큰 차이점은 큐에 있는작업을 이동할수있는지 없는지가 되겠습니다.** 101 | 102 | #### Q) 프로세스 관리가 필요한 이유는무엇일까요? 103 | - 멀티프로그래밍이 지향하는것이 CPU이용률을 최대한 높히는건데, 이때 시스템자원을 효율적으로 사용하기위해서 관리가 필요합니다. 104 | 105 | #### Q) 스레드 스케줄링은 어떻게 되나요? 106 | - 스레드 라이브러리의 기능을통해 제어합니다. 동일한 프로세스내에 있는 스레드들끼리는 우선순위에 따라 스케줄링되지만 라이브러리마다 프로그래머가 스레드의 우선순위를 변경할수도 있습니다. 107 | 108 | #### Q) 각 자원의 우선순위, CPU대기시간 등의 내용들은 어디에 저장될까요? 109 | - PCB에 Process Priority 라는 공간에 적재됩니다. 110 | 111 | #### Q) CPU가 여러개일때의 스케줄링 기법에대해 설명해주세요 112 | - 일반적으로 대칭 다중처리라 불리는 각 프로세서가 스스로 스케줄링할수있는 방식으로 접근합니다. 큐 하나를 공통으로 사용하는 방식과, 프로세서별 큐를 가지는 방식이있습니다. 113 | - 멀티프로세서 환경에서는 **동기화문제**를 신경써줘야합니다. 여러 CPU들이 동시에 사용하는 큐가 있다고 가정하면 동시성 문제가 생길수있기때문입니다. 이로인해 큐를 하나만사용하는 단일 큐 스케줄링은 멀티프로세서 환경에서 락을 삽입해야하기때문에 확장성이 결여되고, 성능이 저하될수있습니다. 반면 멀티큐 스케줄링에서는 작업이 각각 독립적으로 스케줄되기때문에 동기화 문제를 피할수 있습니다. 114 | 115 | 116 | - **캐시친화성**도 고려해야합니다. 117 | 118 | ![image](https://user-images.githubusercontent.com/59333182/226159280-97bfaffb-f4d2-4ffa-a81c-560f10150d4d.png) 119 | 120 | 먼저 설명드릴점은 cpu에서 프로세스가 실행될때 프로세스는 해당 cpu캐시와 TLB에 상태정보를 올려놓게 되고 이 일부정보로 인해 **같은 CPU에서 실행되면 더 빨리 실행**될수있습니다. 121 | 122 | ![image](https://user-images.githubusercontent.com/59333182/226157747-6e3a0f1a-c2e0-492a-a1f0-a70a6f606677.png) 123 | 124 | 위와 같이 단일큐가 있고 4개의 CPU가 있다고 가정해보겠습니다. 각 CPU는 큐 하나를 공유해서 작업을 선택하기때문에 하나의 큐에있는 A,B,C,D,E는 **여러 cpu에 나누어져 실행**하게되어 아래와 같은 그림상태가 됩니다. 125 | 126 | ![image](https://user-images.githubusercontent.com/59333182/226157954-a2f601bc-80a1-423b-b0d6-86bd42af2961.png) 127 | 128 | 하나의 작업이 여러 CPU에서 실행되기때문에 캐시친화적이지 않다고볼수있습니다. 물론 단일큐도 이문제를 해결하기위해 가능한 동일한 CPU에서 하나의 작업이 실행되도록 시도하지만 구현 자체가 복잡하고 이 자체가 비용일수있습니다. 129 | 130 | 멀티 큐 스케줄링 기법은 CPU 개수가 증가할수록 큐의 개수도 증가할수 있으며, 이문제를 해결합니다. 2개의 CPU와 4개의 작업이 있다고 가정해보면 아래그림과 같습니다. 131 | 132 | ![image](https://user-images.githubusercontent.com/59333182/226158524-856bd338-493b-4320-afbf-0e1123df6de4.png) 133 | 134 | 각 큐는 스케줄링 정책이 있을것이고 라운드로빈이라고 가정해보면 스케줄은 아래와같이 생성될수있습니다. 135 | 136 | ![image](https://user-images.githubusercontent.com/59333182/226158549-ff0faa66-f297-4fe7-8d05-7c14b5ce0f81.png) 137 | A,B,C,D 각각의 작업은 하나의 CPU에서 고정적으로 실행되어 캐시친화적이라고 볼수있습니다. 138 | 139 | 정리하자면 일반적으로 큐하나를 여러 CPU에서 공통으로 사용하는방식, CPU별 큐를 가지게되는 멀티큐 스케줄링방식을 사용하게되며 이는 각각 장단점이 있으며 **동기화, 캐시친화성, 작업의 불균형(피드백 큐같이 이동하는방식으로 해결)** 을 고려해야합니다. 140 | 141 | 142 | 143 | #### 사진,내용에 대한 출처 144 | - https://pages.cs.wisc.edu/~remzi/OSTEP/Korean/07-cpu-sched.pdf 스케줄링 알고리즘 145 | - https://pages.cs.wisc.edu/~remzi/OSTEP/Korean/08-cpu-sched-mlfq.pdf 멀티레벨 피드백 큐 146 | - https://pages.cs.wisc.edu/~remzi/OSTEP/Korean/10-cpu-sched-multi.pdf 멀티프로세서 스케줄링시 고려해야할점 147 | -------------------------------------------------------------------------------- /Operating System/Cache Memory & Memory Layered.md: -------------------------------------------------------------------------------- 1 | # Cache Memory 2 | 3 | ### 캐시메모리 및 메모리 계층성에 대해서 설명해주세요. 4 | 5 | * **캐시 메모리는 속도가 빠른 장치와 느린 장치간의 속도차에 따른 병목현상을 줄이기 위한 메모리**입니다. 기존의 캐시메모리는 CPU와 메모리 사이에 위치했으나, 현재 대부분의 L1, L2 캐시는 CPU 내부에 존재하고, L3 캐시만 메인보드에 위치하는데, 최근에는 L1, L2, L3 캐시도 모두 CPU 내부에 위치하고 있습니다. 6 | 7 | * 메모리 계층성은 레지스터, 캐시, 메인 메모리, 보조기억장치로 분류하며, 레지스터가 최상층, 보조기억장치가 최하층에 위치하고 있습니다. 최상층에 가까울수록 사용 빈도가 잦고, 속도가 빠르며, 가격은 비싸고, 용량은 적습니다. 최하층은 그와 반대입니다. 8 | 9 | #### Q) L1, L2, L3 캐시 메모리에 대해서 설명해주세요. 10 | ![image](https://blog.kakaocdn.net/dn/lQYfE/btqzC3IIUQW/B8ctchIdwEZndxSYFlhkI0/img.png) 11 | - 캐시를 분류하면 L1, L2, L3 캐시로 분류할 수 있는데 L1은 CPU 의 각 코어와 밀접하게 위치해있으며, L2 캐시는 CPU 내부에 위치해서 L1 캐시를 공유합니다. 마지막으로 L3가 메인보드에 위치하여 CPU와 메모리 사이에 위치해있습니다. 최근에는 L3 캐시도 CPU 안에 내장되있는 경우가 많습니다. L1에서 L3로 이동할 수록 속도가 상대적으로 느리고, 용량이 더 큽니다. 따라서 캐시메모리를 탐색할 때 L1 -> L2 -> L3 순서로 탐색을 합니다. 12 | #### Q) L1, L2, L3 캐시 메모리는 CPU 내부 어디에 위치하나요? 13 | - L1 캐시는 코어에 가장 가깝게 위치해있습니다. L1은 추가적으로 명령어 캐시(Instruction Cache), 데이터 캐시(Data Cache)로 나눌 수 있습니다. 14 | - L2 캐시는 L1보다는 코어에 덜 가깝게 위치해있습니다. 15 | - L3 캐시는 i5 이전에는 CPU 외부인 메인보드에 위치해있었는데, 최근에 등장하는 CPU는 L3 캐시가 CPU 내부로 들어와있습니다. 16 | 17 | #### Q) 메모리 계층을 분류한 이유와 이점에 대해서 설명해주세요. 18 | - **컴퓨터의 설계에 있어, 각각의 특징이 있는 서로 다른 여러 종류의 기억 장치를 함께 사용하여 최적의 효율을 낼 수 있게 하는 것**입니다. 빠른 저장 장치는 용량에 비해 가격이 비싸고, 용량이 넉넉한 저장 장치는 처리 속도가 느립니다. 19 | 그러나 컴퓨터가 행하는 작업은 매우 다양하고, 빠른 속도가 필요한 상황도 있지만 단순히 많은 내용을 천천히 읽고 쓰는 작업도 그만큼 많습니다. 이렇듯 상황에 맞게 여러 저장 장치를 각각 목적에 맞게 사용할 수 있도록 하여 싸고 성능 좋은 컴퓨터를 구현하는 설계하기 위해 메모리 계층을 분류하였습니다. 20 | 21 | #### Q) 캐시는 데이터를 어떻게 관리하는지 설명해주세요. 22 | - 캐시 내부의 데이터는 임시 데이터입니다. 따라서 원본 데이터의 내용이 바뀌면 캐시 또한 데이터가 바뀌어야 하는데, 임시 데이터이기 때문에 원본 데이터가 바뀌었다고 해서 바로 업데이트 되지 않습ㄴ다. 따라서, 캐시를 저장할 때 만료되는 시간인 TTL을 명시해서 캐시는 해당 시간 내에서만 유효하고 만료 시간이 경과하면 사용할 수 없도록 하고 있습니다. 그러나, 만료 시간 외에도 캐시의 유효성을 확인할 수 있는 방법이 2가지가 더 있습니다. 23 | - 캐시가 사용될 때마다, 원본 데이터가 업데이트 된 시간과 캐시가 생성된 시간을 비교하여 캐시의 유효성을 판별하는 방식입니다. 단, 이 방법은 캐시가 사용될때마다 추가적으로 확인하는 절차가 필요하여 오버헤드가 발생합니다. 24 | - 데이터가 수정이 되는 코드가 수행될 때마다 해당 데이터와 연관된 캐시를 무력화시키는 방법입니다. 캐시를 세밀하게 관리가 가능하여 이상적으로 설계되었을 때 가장 좋은 효율을 발휘합니다. 단, 코드로 캐시를 관리하기 때문에 에러가 발생하기 쉽고 관리가 어렵습니다. 25 | 26 | > Redis의 캐시 전략 4가지 27 | - Redis는 Cache-Aside(Look-Aside), Read-Through(Lazy-Loading), Write-Through, Write-Back(Write-Behind), Write-Around 28 | 총 5가지의 캐시 전략이 있습니다. 29 | 30 | image 31 | 32 | - **Cache-Aside** 33 | - **데이터를 찾을 때 캐시에 저장된 데이터가 있는지 우선적으로 확인하는 전략**입니다. 34 | 이때 캐시 미스가 발생하면 DB 에서 조회합니다. 캐시와 DB가 분리되어 가용돼서 원하는 데이터만 별도로 구성하여 캐시에 저장이 가능하기 때문에 반복적인 읽기가 많은 호출에 적합하고, Read-Through에 비해서 캐시 장애 대비 구성이 되어있습니다. 하지만, 데이터 정합성 문제가 발생할 수 있습니다. 35 |
36 | image 37 | 38 | - **Read-Through** 39 | - **캐시에서만 데이터를 읽어오는 전략**입니다. 40 | 데이터 동기화를 라이브러리나 캐시 제공자에게 위임합니다. 캐시에서만 데이터를 불러오기 때문에 캐시와 DB간의 데이터 동기화가 항상 이루어져서 데이터 정합성 문제는 없으나 속도가 느리다는 단점이 있습니다. 또한, Redis가 다운 될 경우 서비스 이용에 제한이 생깁니다. 41 |
42 | image 43 | 44 | - **Write-Through** 45 | - **데이터베이스와 Cache에 동시에 데이터를 저장하는 전략**입니다. 46 | 데이터를 저장할 때 먼저 캐시에 저장한 다음 바로 DB에 저장하기 때문에 캐시의 데이터는 항상 최신 상태로 유지될 수 있습니다. 하지만 자주 사용되지 않는 불필요한 요소들도 저장을 하고 매 요청시마다 두번의 Write 발생으로 인해 성능 저하가 발생합니다. 따라서 데이터 유실이 절대로 발생하면 안되는 상황에 적합합니다. 47 |
48 | image 49 | 50 | - **Write-Back** 51 | - **캐시와 DB 동기화를 비동기적으로 수행**합니다. 52 | 데이터를 저장할 때 DB에 바로 저장하지 않고, 캐시가 마치 Queue 처럼 동작하여 캐시에 모았다가 일정 주기에 DB에 반영합니다. 따라서 Write-Through에 비해서 쓰기 쿼리 회수 비용과 부하를 줄일 수 있습니다. 따라서, Write가 많을 경우에 사용하는 것이 좋습니다. 하지만 캐시에 데이터가 모아진 상태에서 캐시에서 오류가 발생하면 해당 데이터를 소실할 수 있다는 문제점이 있습니다. 53 |
54 | image 55 | 56 | - **Write-Around** 57 | - **캐시 미스가 발생할 경우에만 캐시에도 데이터를 저장하고, 그 외에 경우에는 모든 데이터를 DB에 저장**합니다. Write-Through 보다 훨씬 빠르지만, 데이터의 정합성이 지켜지지 않는다는 문제가 있습니다. 58 | 59 | #### Q) 캐시의 지역성에 대해서 설명해주세요. 60 | - 캐시는 참조 지역성의 원리에 근거해서 데이터를 저장합니다. 61 | 참조 지역성의 원리는 시간 지역성, 공간 지역성, 순차 지역성 세 가지로 분류할 수 있는데, 이 때 순차 지역성은 공간 지역성과 비슷하여 보통 시간 지역성, 공간 지역성 두 가지로 분류합니다. 62 | - 시간 지역성은 최근 사용했던 메모리를 빠른 시간 안에 참조한다는 개념이고, 공간 지역성은 참조된 메모리 근처의 메모리를 참조한다는 개념입니다. 63 | 64 | #### Q) 캐시의 지역성을 기반으로, 이차원 배열을 탐색했을 때의 성능 차이에 대해서 설명해주세요. 65 | - 한 배열 내에서 가로로 접근하게 되면 하나의 배열의 근접한 메모리의 주소를 캐시의 메모리 만큼 바로 탐색이 가능하여 공간 지역성에 대한 장점을 활용할 수 있습니다. 그러나 세로로 탐색을 하게 되면 인접한 요소가 아닌, 다른 새로운 배열의 요소에 탐색을 하기 때문에, 가로로 탐색하는 것에 비해 좋지 않은 공간 지역성을 가진 것이라고 볼 수 있습니다. 66 | 67 | > L1 캐시는 세부적인 영역으로 추가적으로 나누어지는데, 이에 대해서 설명해주세요. 68 | - L1 캐시는 코어와 가장 밀접해있는 캐시입니다. 주로 명령어나 데이터를 다룰 때 사용을 하게 되는데, 이러한 명령어나 데이터도 주소 버스와 데이터 버스를 통해서 이동을 해야하는 과정을 거치게 되면 시간 지연이 발생해서 자주 사용하는 명령어와 데이터는 L1 캐시에 적재를 하게 되는데, 이 때, 이 캐시의 속도를 더 향상 시키기 위해 Instruction Cache와 Data Cache로 나누고 있습니다. 69 | 70 | #### Q) 캐시 메모리와 메인 메모리의 매핑 방식에 대해서 설명해주세요. 71 | - 캐시 메모리는 메인 메모리에 비해서 용량이 작아서 1:1로 매핑이 불가능합니다. 이에 따라 특정 자료구조를 이용하여 캐시 메모리에 저장하는데, 이러한 저장 방식을 캐싱 라인이라고 합니다. 그리고 이 캐싱 라인은 3가지 방법이 있습니다. 72 | - **직접 매핑** 73 | - 메인 메모리를 일정한 크기의 블록으로 나누고 블록 크기 word에 따라 캐시의 정해진 위치에 매핑하는 방식입니다. 74 | - 캐시 메모리의 각 구역에 지역성의 원리에 위배 된 여러 개의 데이터들이 같이 담길 수 있어서, 캐시 히트 비율이 떨어집니다. 75 | - **연관 매핑** 76 | - 캐시 메모리에 빈 공간에 마음대로 주소를 저장하는 방식입니다. 77 | - 실제로 자주 사용되는 데이터들만 캐시 메모리에 적재를 하기 때문에, 캐시 히트 비율은 높아지나, 캐시 메모리에 담긴 데이터를 찾을 때 모든 태그를 병렬적으로 검사해야해서, 복잡하고 비용이 많이 발생합니다. 78 | - **세트 연관 매핑** 79 | - 직접 매핑의 장점과 연관 매핑의 장점을 합친 기법입니다. 80 | - 블럭 단위로 나누고, 빈 공간에 마음대로 저장을 합니다. 이때, 세트 당 캐시 라인의 수에 따라 m-way-set 연관 매핑이라고 합니다. 81 | - 세트 연관 매핑에서 m을 1로 두면, 이는 직접 연관 매핑이 됩니다. 또, 세트 수를 캐시 라인 수와 동일하게 두면 이는 연관 매핑이 됩니다. 82 | 83 | #### Q) 캐시 동기화에 대해서 설명해주세요. 84 | - 캐시가 사용될 때마다, 원본 데이터가 업데이트 된 시간과 캐시가 생성된 시간을 비교하여 캐시의 유효성을 판별하는 방식입니다. 단, 이 방법은 캐시가 사용될때마다 추가적으로 확인하는 절차가 필요하여 오버헤드가 발생합니다. 85 | - 데이터가 수정이 되는 코드가 수행될 때마다 해당 데이터와 연관된 캐시를 업데이트시키는 방법입니다. 캐시를 세밀하게 관리가 가능하여 이상적으로 설계되었을 때 가장 좋은 효율을 발휘합니다. 단, 코드로 캐시를 관리하기 때문에 에러가 발생하기 쉽고 관리가 어렵습니다. 86 | 87 | - 캐시 동기화는 캐시 쓰기 요청이 어떤 목적이냐에 따라 다릅니다. 크게 3가지로 구분 할 수 있습니다. 88 | - Write Around 89 | - 쓰기 작업 중에 캐시는 건들지 않고, 읽기 작업 시에 Cache Miss가 발생하면 업데이트 됩니다. 90 | - Write Through 91 | - 쓰기 작업 시 캐시를 동기화 한 이후에, 데이터를 반환합니다. 따라서, 캐시를 항상 최신 상태를 유지할 수 있지만, 동기식으로 갱신한 이후 최종 데이터 반환이 되기 때문에 속도 면에서 성능이 떨어질 수 있습니다. 92 | - Write Back 93 | - 동기화 작업을 비동기로 하는 방법입니다. 쓰기 작업이 매우 많은 경우에 택하는 방법이고, 일정량의 데이터를 모아놓았다가 한 번에 업데이트합니다. 그러나, 구현이 복잡하고, 일정량의 데이터가 모아져 있는 상태에서 장애가 발생하면 데이터가 유실될 수 있는 문제가 있습니다. 94 | 95 | #### 사진, 내용에 대한 출처 96 | - https://bcp0109.tistory.com/364 97 | - https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-%EC%BA%90%EC%8B%9CCache-%EC%84%A4%EA%B3%84-%EC%A0%84%EB%9E%B5-%EC%A7%80%EC%B9%A8-%EC%B4%9D%EC%A0%95%EB%A6%AC 98 | - https://rebro.kr/180 99 | -------------------------------------------------------------------------------- /Operating System/Context Switching & PCB.md: -------------------------------------------------------------------------------- 1 | # PCB와 Context Switching 2 | 3 | 4 | * Process Control Block의 약자인 PCB는 **프로세스의 메타 정보들을 저장해두는 커널에 있는 자료구조** 입니다. PCB에 저장되는 프로세스 메타정보에는 다음과 같이 8개의 메타 정보를 저장합니다. 5 | 1. `Process ID` : PID(Process Identification Number) 주로 PID 라고 줄여서 부릅니다. 6 | : 프로세스 고유 식별 번호 7 | 2. `Process State`(프로세스 상태) 8 | : 프로세스의 현재 상태(생성, 준비, 실행, 대기, 종료)를 기억 시킵니다. 9 | 3. `Program Counter`(계수기) 10 | : 다음에 실행되는 명령어의 주소를 기억시킵니다. 11 | 4. `Process Priority`(스케줄링 정보) 12 | : 프로세스 우선순위 등과 같은 스케줄링 관련 정보를 기억시킵니다. 13 | 5. `CPU Registers` 14 | : 프로세스의 레지스터 상태를 저장하는 공간 등, CPU 내 범용 레지스터, 데이터 레지스터, 세그먼트 레지스터 등이 갖고 있는 값을 기억시킵니다. 15 | 6. `Owner`(계정 정보) 16 | : CPU 사용시간의 정보(Quantum), 각종 스케줄러에 필요한 정보를 기억시킵니다. 17 | 7. `기억장치 관리 정보` 18 | : 프로그램이 적재될 기억 장치의 시작 지점(베이스 레지스터), 종료 지점(한계 레지스터), 페이지 테이블 등의 정보를 기억시킵니다. 19 | 8. `입출력 정보` 20 | : 프로세스 수행 시 필요한 주변 장치, 파일들의 정보를 기억시킵니다. 21 | 22 | 23 | 24 | * Context Switching 이란 **CPU가 이전의 프로세스 상태를 PCB에 보관하고, 또 다른 프로세스의 정보를 PCB로 부터 읽어 준비 상태 큐에 있던 프로세스를 실행 상태로 옮기는 것** 을 말합니다. 25 | Context Switching 은 주로 인터럽트가 발생하거나, 실행 중인 CPU 사용 허가 시간(Time Quantum)을 모두 소모(타이머 인터럽트 == 타입아웃 인터럽트 발생) 하거나, I/O 입출력을 위해 대기해야 하는 경우 발생합니다. 26 | 27 | #### Q) Context Switching이 일어날 때, 캐시 관련해서도 프로세스와 스레드의 처리 방법이 다르다고 알고 있습니다. 이를 설명해주세요. 28 | - 프로세스는 메모리 영역은 code, data, heap, stack 영역을 독립적으로 가지고 있습니다. 이 때, 캐시는 참조 지역성의 원리에 의해서 저장이 되는데 참조 지역성의 원리는 시간 지역성과 공간 지역성 두 개로 나뉩니다. 이때, 시간 지역성은 '최근에 접근했던 메모리 공간에 다시 접근하려는 경향' 을 의미하며, 공간 지역성은 '접근한 메모리 공간 근처를 접근하려는 경향' 을 의미합니다. 29 | **프로세스는 컨텍스트 스위칭이 발생할 때, 독립적인 메모리 영역을 가지고 있기 때문에 메모리 공간 자체가 변경이 일어나게 되는데, 이럴 경우 캐시 메모리의 캐시 히트가 떨어져서 캐시 메모리를 비워줘야 합니다.** 30 | 그러나 스레드의 메모리 영역은 프로세스와 동일한 영역으로 구성되어 있지만 code, data, heap 영역을 공유하고, stack 영역만 독립적으로 가지고 있습니다. 따라서, **공유된 데이터들을 사용하여 캐시 히트가 프로세스에 비해 많이 낮아지지 않기 때문에, 캐시 메모리를 비우지 않아도 된다는 장점이 있습니다.** 31 | 32 | #### Q) 프로세스는 여러개의 스레드를 가지고 있는데, 이 스레드들에 대한 정보를 어떻게 가지고 있는가 33 | - **스레드에 대한 관리는 스레드 제어 블록(TCB)에서 관리를 할 수 있습니다.** 이때, TCB는 시스템에서 생성된 스레드를 나타냅니다. TCB에는 다음과 같은 정보가 저장되어 있습니다. 34 | 1. `Thread ID` 35 | 2. `Thread Status` 36 | 3. `CPU 정보 (PC, Register)` 37 | 4. `Thread Priority` 38 | 5. `스레드의 생성을 트리거한 프로세스를 가리키는 포인터` 39 | 6. `스레드에서 만든 스레드를 가리키는 포인터` 40 | 41 | 스레드는 커널 영역에서 실행되어야 합니다. 이때 `LWP(Light Weight Process)` 라는 용어가 등장합니다. LWP는 운영 체제에 따라 의미를 다르게 두고 있습니다. 42 | 리눅스의 경우 사용자 레벨 에서의 스레드와 프로세스는 구분이 가능하지만, 스레드가 실행되기 위해서는 커널 영역으로 올라와야하고, 커널 영역에서 cpu해당 스레드를 봤을 때는, 작은 프로세스를 처리한다는 의미로 LWP 를 사용하고 있습니다. 43 | 대부분의 운영체제에서는 사용자 영역 내에서의 스레드는 커널 영역으로 스레드가 이동이 되어서 실행이 되어야 합니다. 이때, 사용자 영역에서 커널 영역으로 스레드를 이동시키는데 이를 도와주는 영역을 LWP 로 사용하고 있습니다. 이때 스레드 간 LWP로 이동되기 위해서 각 스레드끼리 경쟁이 발생하는데, 이를 `PCS(Process-contention scope)` '프로세스 경쟁 범위'라고 하고, LWP로 이동하고 나서도 CPU에 매핑되기 위해서도 스케줄링이 필요합니다. 이러한 것을 `SCS(System Contention Scope)` '시스템 경쟁 범위' 라고 합니다. 44 | 45 | #### Q) 프로세스와 스레드는 Context Switching이 발생할 때 어떤 차이가 있는가 46 | - 프로세스는 code, data, heap, stack 영역을 독립적으로 가지고 있습니다. 따라서 Context Swtiching이 발생할 때, 독립적인 메모리를 포함하여, 캐시 메모리를 비워줘야 해서 스레드에 비해 상대적으로 많은 오버헤드가 발생합니다. 47 | 이와 달리 스레드는 code, data, heap 영역을 공유하고 stack 영역만 독립적으로 가지고 있기 때문에, 캐시 메모리를 비우지 않아도 되고 프로세스에 비해 상대적으로 적은 오버헤드가 발생합니다. 48 | 49 | #### Q) Context Switching 에서 프로세스 수행 중에 입출력 상태로 전환되어서 대기 상태로 전환 되는데, CPU를 어떻게 하는 것이 효율적인가? 50 | - Context Switching 에서 입출력 인터럽트가 발생하게 되면 실행 상태에 있던 프로세스는 대기 상태로 전환됩니다. 이때, CPU 스케줄러에 의해서 해당 프로세스의 자원은 반환됩니다. 이후 CPU가 입출력 인터럽트의 완료를 기다리는 동안 준비 상태 큐에 있는 프로세스 중에서 스케줄링 알고리즘에 따라 실행 상태로 들어가고, 대기 상태에 있던 프로세스는 입출력 작업이 완료되게 되면 다시 준비상태 큐로 들어갑니다. 51 | 52 | #### Q) Context Switching이 인터럽트가 발생할 때만 발생하는가? 53 | - Context Switching은 다음과 같은 상황에 발생합니다. 54 | 1. 멀티태스킹(Multitasking) 55 | : 실행 가능한 프로세스들이 운영체제의 스케줄러에 의해 조금씩 번갈아가며 수행된다. 56 | 2. 인터럽트 핸들링(Interrupt handling) 57 | : I/O Request, time slice expired, fork a child, wait for an interrupt 58 | 3. 사용자와 커널 모드 전환(User and kernel mode switching) 59 | 60 | 따라서, **모든 상황에서 인터럽트가 발생하므로 인터럽트가 발생할 때에만 발생한다고 할 수 있습니다.** 61 | 62 | #### Q) 인터럽트는 무조건 들어오는 순서대로 처리를 하는가? 63 | - 아닙니다. **CPU는 인터럽트를 우선순위에 따라 처리할 수 있습니다.** NMI(Non-Maskable interrupt) 가 발생한 경우 CPU는 해당 인터럽트 부터 처리합니다. 여기서 NMI는 무시될 수 없는 interrupt 입니다. 몇몇 심각한 사건(정전, 하드웨어 고장 등 어찌할 수 없는 오류)등이 해당됩니다. 64 | 많은 컴퓨터에서는 프로그래머블 인터럽트 컨트롤러(PIC : Programmable Interrupt Controller)라는 하드웨어를 사용하여 인터럽트 요청들의 우선순위를 판별합니다. 65 | 66 | 67 | > #### Q) 프로세스 컨트롤 블록이 어떤 자료구조로 관리 되는지 알고 있는가 68 | 69 | - PCB는 **Doubly Linked List 방식으로 관리**됩니다. 70 | PCB의 List Head에 PCB들이 생성될 때마다 붙게 됩니다. 주소 값으로 연결이 이루어져 있는 연결리스트이기 때문에 삽입 삭제가 용이합니다. 71 | > ~연결 리스트의 구조를 사용함으로써 삽입 `O(1)` 은 용이하다고 생각되지만 (항상 list의 헤드에 붙이기 때문에 위치를 알고 있음.) 삭제에 있어서는 해당 PCB의 위치를 찾고 `O(n)` 연결을 끊는 것 `O(1)` 이기 때문에, 삭제는 용이한지 잘 모르겠습니다..ㅠ 그냥 연결리스트와 배열과 비교를 했을 때 연결 리스트의 탐색은 제외하고 삽입 삭제만 바라봤을 때의 대해서 얘기한거겠죠?~ 동윤님 답변으로 해결되었습니다! `node.prev.next = node.next;` 72 | 73 | > #### Q) Context Switching 시에 주소공간에 대한 캐시 처리가 어떻게 이루어지는지 설명해주세요. 74 | 75 | - TLB를 이해하기 전에 먼저 페이지 테이블을 이해 할 필요가 있습니다. 76 | 기존의 프로세스들을 메모리에 적재할 때, 순차적으로 적재를 하게 되면 단편화 문제가 발생하기 때문에, 이를 방지하기 위해서 가상 메모리 기법이 생겼고, 가상 메모리 기법은 세그멘테이션과 페이징 기법으로 나눌 수 있습니다. 77 | 가상 메모리 기법으로 분할 된 메모리의 페이지들은 페이지 테이블에서 관리를 하게 되는데, 메모리에 실제 주소를 참조하기 위해서는 78 | 1. 페이지 테이블에 한번 접근(fetch) 79 | 2. 페이지 테이블을 기반으로 실제 메모리로 접근 (Memory Access) 80 | 81 | 와 같은 과정이 필요한데, 실행할 때마다 같은 table에 속한 메모리 주소를 찾고 다시 메인 메모리에 접근해야 하는 불필요한 일이 발생합니다. 82 | 이런 메모리의 접근을 줄이기 위해서 TLB가 등장했고, TLB는 page table의 임시저장 캐시 역할을 합니다. TLB는 L3 캐시에 위치해있습니다. 이때 TLB에는 최근에 읽었던 변환될 물리 주소를 매핑해서 저장을합니다. 따라서 **TLB를 활용하면 한 프로세스 내의 다른 스레드를 Context Switching 하는 경우 invalid가 발생하지 않아, 주소 공간을 참조하는데 하드웨어 적으로 이점**을 볼 수 있고, **프로세스가 Context Switching을 하게 되는 경우, kernel 주소 공간을 제외한 모든 영역을 invalid 하기 때문에, 스레드와 달리 손해**를 보게 됩니다. 83 | 84 | #### 사진 & 내용 출처 85 | - https://velog.io/@jaypyon/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%A0%9C%EC%96%B4-%EB%B8%94%EB%A1%9DPCB%EC%9D%B4%EB%9E%80 86 | - https://afteracademy.com/blog/what-is-context-switching-in-operating-system/ 87 | - https://spurdev.tistory.com/13 88 | - https://velog.io/@gothae/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-PCB%EC%99%80-Context-Switching 89 | -------------------------------------------------------------------------------- /Operating System/Deadlock.md: -------------------------------------------------------------------------------- 1 | # Deadlock 2 | 3 | ### 데드락에 대해 설명해주세요 4 | * 프로세스가 자원을 얻지 못해 다음 처리를 하지 못하는 상태로, 시스템적으로 한정된 자원을 동시에 여러 곳에서 사용하려고 할 때 발생합니다. 데드락은 4가지 조건이 충족이 되어야 발생을 하고, 그 조건에는 상호배제, 점유 대기, 비선점, 순환 대기가 있습니다. 5 | 6 | 7 | 8 | #### Q) 데드락이 발생하는 조건에 대해서 설명해주세요. 9 | - 데드락은 상호 배제, 점유 대기, 비선점, 순환 대기 4가지 조건이 충족되어야 발생합니다. 10 | - `상호 배제` : 자원은 한 번에 한 프로세스만이 사용할 수 있어야 한다. 11 | - `점유 대기` : 최소한 하나의 자원을 점유하고 있으면서, 다른 프로세스에 할당된 자원을 점유하기 위해 대기하는 프로세스가 존재해야 한다. 12 | - `비선점` : 이미 할당된 자원을 강제로 빼앗을 수 없다. 13 | - `순환 대기` : 대기 프로세스의 집합이 순환 형태로 자원을 대기하고 있어야 한다. 14 | 15 | 16 | 17 | > #### Q) 각각의 조건들에 대한 예방 방법을 설명해주세요. 18 | - 예방을 하기 위해서는 각각의 조건들에 대해 부정을 하면 됩니다. 19 | - `상호 배제 부정` : 여러 개의 프로세스가 동시에 공유자원을 사용할 수 있게 합니다. 단, 이럴 경우 동기화 문제가 발생할 수 있습니다. 20 | - `점유 대기 부정` : 프로세스가 실행되기 전에 필요한 모든 자원을 할당하여 프로세스 대기를 없애거나, 자원이 점유되지 않은 상태에서만 자원 요청을 받도록 합니다. 21 | - `비선점 부정` : 모든 자원에 대한 선점을 허용합니다. 22 | - `순환 대기 부정` : 자원을 선형으로 분류하여 고유 번호를 할당하고, 각 프로세스는 현재 점유한 자원의 고유번호보다 앞이나 뒤 한쪽 방향으로만 자원을 요구하도록 합니다. 23 | #### Q) 데드락을 해결하기 위한 방법 중 회복에 대해서 설명해주세요. 24 | - 데드락을 회복하기 위해서는 먼저 데드락을 탐지하는 과정이 필요합니다. 데드락을 탐지하기 위해 은행원 알고리즘을 사용해야 합니다. 25 | - `은행원 알고리즘` : 자원의 할당을 허용하는지에 관한 여부를 결정하기 전에, 미리 결정된 모든 자원들의 최대 가능한 할당량을 가지고 시뮬레이션 해서 안정 상태에 들 수 있는지 여부를 검사하는 것입니다. 26 | - 이러한 알고리즘을 통해 데드락을 탐지했다면, 프로세스를 1개 이상을 중단 시키거나, 자원을 선점시키는 방식으로 데드락을 회복할 수 있습니다. 27 | - 이때, 중단 시키는 작업은 프로세스의 부분 결과가 폐기될 수 있고, 회복하기 위해서는 탐지 알고리즘을 계속 수행해주어야 하기 때문에, busy waiting 문제가 발생할 수 있습니다. 28 | 29 | #### Q) 데드락이 발생하는 4가지 조건 중 왜 3 가지 조건을 만족하면 데드락이 발생하지 않는지에 대해서 설명해주세요. 30 | - 데드락이 발생하기 위한 4가지 조건 중 하나의 조건을 충족하지 않는 다는 것은 어떠한 한 가지 조건에 대해 예방을 했다고 말 할 수 있습니다. 따라서, 데드락이 발생하지 않습니다. 31 | 32 | > #### Q) 자바에서 데드락이 발생할 수 있을까요? 33 | - 멀티 쓰레드 환경으로 동작하게 하고, 동기화 설계를 잘못해준 경우에 데드락이 발생할 수 있습니다. 34 | - 이를 이해하기 위하여, synchronized에 대해서 이해 할 필요가 있습니다. 35 | - synchronized 키워드는 동기화가 필요한 메서드나 코드 블럭 앞에 사용하여 동기화 할 수 있습니다. synchronized로 지정된 임계영역은 한 스레드가 이 영역에 접근하여 사용할 때 lock이 걸림으로써 다른 스레드가 접근을 할 수 없게되고, 해당 스레드가 임계영역의 코드를 실행 후 벗어나게 되면 unlock 상태가 되어 그때서야 대기하고 있던 다른 스레드가 이 임계영역에 접근하여 lock을 걸고 사용할 수 있게 됩니다. 36 | - 데드락이 발생하는 설계 상의 오류는 `synchronized`안에 `synchronized`를 또 선언 할 경우에 발생합니다. 37 | ```java 38 | private static void sum(Node n1, Node n2) { 39 | // 0부터 9까지 반복한다. 40 | for (int i = 0; i < 10; i++) { 41 | // n1에 lock을 건다. 42 | synchronized (n1) { 43 | // n2에 lock을 건다. 44 | synchronized (n2) { 45 | // 값을 가져와서 46 | int data = n1.getData(); 47 | // i만큼 더한다. 48 | n1.setData(data + i); 49 | // 값을 가져와서 50 | data = n2.getData(); 51 | // i만큼 더한다. 52 | n2.setData(data + i); 53 | } 54 | } 55 | // 콘솔 출력 56 | System.out.println(Thread.currentThread().getName() + " i = " + i); 57 | // 스레드 1초 대기 58 | sleep(); 59 | } 60 | } 61 | ``` 62 | - 다음과 같은 상황에서 쓰레드가 2개가 있을 때 첫 쓰레드에 n1, n2 두번째 쓰레드에 n2, n1을 넣었다고 했을 때, 멀티 쓰레드에서는 병렬 처리를 하기 때문에, n1과 n2가 동시에 락을 획득하는 상황이 생길 수 있습니다. 63 | - 동시에 n1과 n2에 락이 걸렸을 때, 다음 스탭에서 첫번째 스레드에서 n2에 접근을 하려고 할 때, n2는 락이 걸려있기 때문에 wait상태가 되고, 이어서 두번째 스레드에서도 n1으로 들어가려고 하니 락이 걸려있어 wait 상태로 빠지게 됩니다. 64 | - 이렇게 두 스레드는 서로의 lock이 풀리는 것을 기다려야 하는 상황이 발생하는 데드락에 빠지게 되는 것입니다. 65 | - 따라서, 각각의 노드들에 대한 synchronized를 사용하지 않고, 해당 함수의 접근에 있어서 동기화 처리를 하게 되면 데드락 문제가 발생하지 않습니다. 66 | > #### Q) synchronized에 대해서 간략하게 설명해주세요. 67 | 68 | ![image](https://tecoble.techcourse.co.kr/static/ff6bf378623f4cbfe190196dcffdc476/1255e/java-monitor.png) 69 | - 자바의 synchronized 키워드는 스레드간 동기화를 시켜 데이터의 thread-safe를 보장합니다. 즉, 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터에 접근 할 수 없도록 막는 개념입니다. 70 | - synchronized는 상호 배제를 위해 monitor 기법을 채택하고 있습니다. 여기서 monitor 기법이란, mutex, semaphore 같은 경우에는 직접 lock 변수 혹은 wait, signal을 어떠한 동기화를 위해 직접 명시해야 하는 문제로 인해 개발자가 실수하여 잘못 설계되는 경우가 발생할 수 있습니다. 이를 개선하기 위해 상호 배제를 프로그램으로 구현한 것입니다. 71 | ```java 72 | public static synchronized Instance getInstance() { 73 | if (Objects.isNull(instance)) { 74 | instance = new Instance(); 75 | } 76 | return instance; 77 | } 78 | ``` 79 | > #### Q) 현대 운영체제에서는 데드락 문제를 어떻게 해결하고 있는지 선택해주세요. 80 | - 힌트 : 예방은 자원 문제가 심해서 회피를 선택합니다. 81 | - 데드락이 드물게 발생을 하게 되면, 데드락을 해결하기 조치가 더 큰 오버헤드를 발생시킬 수 있습니다. 따라서 이를 방지하기 위해 **데드락 무시 기법**을 채택하고 있으며, 교착상태 발생 시 프로세스를 종료하여 재실행하거나, 자원을 선점하여 회복한다고 합니다. 82 | - 교착상태를 회피하기 위해서는 계속해서 탐지를 해야하는데, 현대의 OS에서는 데드락이 드물게 발생하기 드물게 발생하기도 하고, 자원을 요청할 때마다 시스템의 상태를 판단하고 알고리즘을 돌려야하기 때문에, 현대 시스템에서는 회피 방법 사용 시에 발생하는 오버헤드를 감당하는 시스템이 없다고 합니다. 83 | 84 | #### Q) 데드락이 발생하는 시나리오 85 | 86 | ![Image](https://velog.velcdn.com/images%2Fminseojo%2Fpost%2F5cb6568d-be51-42fa-b860-6f02172fbd02%2Fimage.png) 87 | 88 | - 데드락이 발생하는 시나리오 중에서 가장 유명한 시나리오는 식사하는 철학자 입니다. 식사하는 철학자의 진행 방식은 다음과 같습니다. 89 | 1. 일정 시간 생각을 한다. 90 | 2. 왼쪽 포크가 사용 가능해질 때까지 대기한다. 만약 사용 가능하다면 집어든다. 91 | 3. 오른쪽 포크가 사용 가능해질 때가지 대기한다. 만약 사용 가능하다면 집어든다. 92 | 4. 양쪽의 포크를 잡으면 일정 시간만큼 식사를 한다. 93 | 5. 오른쪽 포크를 내려놓는다. 94 | 6. 왼쪽 포크를 내려놓는다. 95 | 7. 다시 1번으로 돌아간다. 96 | - 이럴 경우 2번을 진행을 하게 되면 모든 철학자들은 포크를 집어들고 있고, 모든 철학자가 오른쪽 포크를 들기 위해 3번 상태에서 머무르는 데드락 상황이 발생합니다. 97 | 98 | #### 사진,내용에 대한 출처 99 | - https://jwprogramming.tistory.com/12 100 | - https://kadosholy.tistory.com/123 101 | - https://tecoble.techcourse.co.kr/post/2021-10-23-java-synchronize/ 102 | - https://velog.io/@minseojo/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%8B%9D%EC%82%AC%ED%95%98%EB%8A%94-%EC%B2%A0%ED%95%99%EC%9E%90-%EB%AC%B8%EC%A0%9C 103 | -------------------------------------------------------------------------------- /Operating System/File System.md: -------------------------------------------------------------------------------- 1 | # File System 2 | 3 | 파일 시스템은 파일을 질서있게 관리하기 위해 파일 시스템을 사용합니다. 파일은 **보조 저장 장치(ex. 디스크)에 정보를 저장하는 단위**이며, 메타데이터와 파일 내용을 따로 저장해두고, 메타 데이터는 i-node 에 의해 관리됩니다. 4 | 5 | ### Q) 유닉스 파일시스템의 i-node 에 관해 간략하게 설명해주세요. 6 | i-node블록은 **메타데이터를 저장하기 위한 자료구조**로, 고유한 정수번호로 생성됩니다. 7 | 하나의 파일에 하나의 inode 생성되어 **각 파일의 위치 정보**를 가리킵니다. 따라서 내가 원하는 파일이 정확히 어떤 위치에 저장되어 있는 지 알 수 있습니다. 8 | 9 | - **i-node (메타 데이터) 리스트** 10 | - **모드** : 파일의 타입과 허가 마스크 11 | - 링크 카운트 : i-node 번호와 함께 entry를 가지고 있는 디렉토리 수 12 | - **사용자 ID** : 파일의 소유자 ID 13 | - **그룹 ID** : 파일의 소유 그룹 ID 14 | - **크기** : 파일의 크기 15 | - **시간** (최근 액세스 시간, 최근 갱신 시간) 16 | - **i-node 시간** : i-node 구조를 마지막으로 수정한 시간 17 | - **블록 목록** : 파일의 첫 번째 세그먼트를 가지고 있는 디스크 블록의 번호목록 18 | - **간접 목록** : 다른 블록들의 목록 19 | 20 | 21 | 22 | > ### Q) 파일시스템과 디스크 개념을 연결해서 파일 시스템이 필요한 이유를 설명해주세요. 23 | > 💡 Hint : 파일은 디스크 단위로 이루어져 있는데 디스크는 byte단위로 읽지 못 함. 24 | 25 | 파일을 블록으로 나누고 블록에 논리적 번호를 구성합니다. 이 파일의 (논리적) 블록을 디스크의 (물리적) 블록에 **디스크 블록 할당 방법을 통해 저장**합니다. 26 | - **연속 할당 (contiguous allocation)** 27 | 28 | 29 | image 30 | 31 | 32 | - **연속된 블록에 파일을 할당하는 방법**입니다. 33 | - **[장점]** 34 | - 디스크 헤더의 이동을 최소화 할 수 있어 **I/O 성능을 높일 수** 있습니다. 35 | - **순차 접근(Sequential Access) 가능** 36 | - **직접 접근(Direct Access)이 가능** 37 | - **[단점]** 38 | - 파일을 할당하고 지우고를 반복하다보면 중간 중간에 빈 공간(hole)이 생기는데 연속 할당은 연속된 공간을 찾아야 하기 때문에 **외부 단편화 문제가 발생**합니다. 39 | - 파일을 저장할 때 **실제 크기를 알 수 없습니다.** 40 | 41 | 42 | **연결 할당 (linked allocation)** 43 | 44 | 45 | image 46 | 47 | 48 | - 연속 할당의 문제점을 해결하기 위해, **링크드 리스트(linked list) 와 같은 방식으로 파일을 할당**합니다. 49 | - **[장점]** 50 | - 새로운 파일을 할당할 때 **비어있는 임의의 블록을 첫 블록으로 선택**합니다, 51 | - 파일이 커지는 경우 **다른 블록을 할당**해서 **기존의 블록과 연결**만 해주면 되기에 연결 할당은 위치와 상관없이 할당이 가능하므로 **외부 단편화 문제가 없습니다.** (= 디스크 낭비가 없다.) 52 | - **[단점]** 53 | - 순차 접근은 가능하지만 **직접 접근은 불가능**합니다. 54 | - 파일의 블록들은 모두 흩어져 있으므로 시작 **블록 번호를 가지고는 원하는 위치의 블록에 바로 접근할 수는 없습니다**. 55 | - **포인터를 저장하는 4 bytes** 이상의 **손해**가 발생합니다. ( *linked list of data blocks* ) 56 | - 각 블록의 마지막에 주소를 저장하는 포인터 공간(4bytes)이 존재하며, 여기서 다음 블록을 가리킴. 57 | - 마지막 블록의 포인터 공간에는 끝임을 나타내는 값이 저장되어 있음. 58 | - **중간 블록의 포인터가 끊어지면** 그 이후의 모든 블록에 **접근하지 못한다**는 특징이 있습니다 (낮은 신뢰성) 59 | - 블록이 **모두 흩어져 있으므로** 디스크 헤더의 움직임이 그 만큼 많이 발생하여 **속도가 느립니다.** 60 | - 이러한 문제를 해결하기 위해 나온 것이 **FAT** 61 | 62 | 63 | 64 | **색인 할당 (indexed allocation)** 65 | 66 | 67 | image 68 | 69 | 70 | - 연결 할당과 같이 데이터를 랜덤한 블록 번호에 할당, 인덱스 블록이라고 부르는 블록에 **할당된 블록 번호(포인터)를 하나의 블록에 따로 저장**합니다. 71 | - 파일 당 하나의 인덱스 블록이 존재 72 | - **[장점]** 73 | - 색인 할당은 인덱스 블록에 할당된 블록을 순서대로 저장하기 때문에 **직접 접근이 가능** 74 | - 연속적으로 할당할 필요가 없으므로 **외부 단편화 문제 또한 발생하지 않음.** 75 | - 색인 할당은 Unix/Linux에서 주로 사용한다. (i-node) 76 | 77 | - **[단점]** 78 | - 작은 크기의 파일인 경우에도 **하나의 블록을 인덱스 블록으로 사용**하기 때문에 **저장 공간이 손실** 79 | - 하나의 인덱스 블록을 가지고는 **크기가 큰 파일을 저장할 수 없음.** 80 | 81 | 82 | > ### Q) 파일 시스템의 Super Block 에 대해 설명해주세요. 83 | image 84 | 85 | 86 | - UNIX 파일 시스템의 구조는 **부트 블록(Boot Block), 슈퍼 블록(Super Block), I-node(Index node) 블록, 데이터 블록**으로 구성됩니다. 87 | 88 | - **부트 블록** : 부팅 시 필요한 코드를 저장하고 있는 블록 89 | - **슈퍼 블록** : 전체 파일 시스템에 대한 정보를 저장하고 있는 블록 90 | - **I-node 블록** : 각 파일이나 디렉터리에 대한 모든 정보를 저장하고 있는 블록 91 | - **데이터 블록** : 디렉터리별로 디렉터리 엔트리와 실제 파일에 대한 데이터가 저장된 블록 92 | 93 | 94 | - 슈퍼 블록의 특징은 95 | - **디스크에 저장되는 가장 중요한 정보**를 담고 있는 블록입니다. 96 | - 디스크의 헤드와 실린더 수, i-node 목록의 헤드, 자유 블록에 대한 정보 97 | - **파일 시스템이 마운트될 때 맨 처음 읽는 정보**입니다. 98 | - 슈퍼블록은 모든 블록 그룹에 똑같은 복사본을 갖도록 시스템이 자동으로 생성됩니다. 99 | - 파일 시스템 손상되었을 때 슈퍼블록을 이용하여 복구 가능합니다. 100 | 101 | 102 | 103 | 104 | > ### Q) 블록 단위로 불러오고 나서 흩어져 있는 블록들에 파일을 불러와야 합니다. 파일을 할당하는 방식 중 연결 할당 방식에 대해 설명해주세요. 105 | - 파일을 할당하는 방식은 크게 연속 할당, 불연속 할당으로 나눌 수 있습니다. 106 | 연속 할당은 파일을 디스크에 연속되게 저장하는 방식으로 한 번의 탐색으로 많은 양을 전송할 수 있으며 접근성이 좋습니다. 하지만, 외부 단편화가 발생하며, 파일의 크기를 키우기가 어렵습니다. 파일의 커질 가능성을 고려해서 미리 큰 공간을 할당한다면 내부 단편화가 발생할 수도 있습니다. 107 | 이러한 문제를 해결하기 위해 불연속 할당이 나왔는데, 불연속 할당은 연결 할당과 색인 할당으로 나눌 수 있습니다. 108 | - 연결 할당은 링크드 리스트로 구현되어 끊겨버리게 되거나 그 이후부터 다시 확인할 수 없다는 단점을 보완하기 위해, FAT가 나왔습니다. 109 | 110 | 111 | ### FAT(File Allocation Table) 시스템 112 | 113 | 114 | image 115 | 116 | 117 | - 다음 블록을 가리키는 포인터들만 모아서 **하나의 테이블(FAT)을 만들어 한 블록에 저장**합니다. 118 | - 기존의 연결 할당 문제점을 대부분 해결합니다. 119 | - **한 번만 읽으면 직접 접근이 가능** 120 | - 중간 블록에 문제가 생겨도 FAT를 통해 **그 다음 블록은 여전히 읽을 수 있음** 121 | - FAT는 매우 중요한 정보이므로 손실 시 복구를 위해 **이중 저장** 122 | - FAT의 각 인덱스 크기는 전체 블록의 개수를 저장할 만큼의 크기를 가지고 있어야 하는데, 현재는 일반적으로 32bit 크기를 사용 : **FAT32** 123 | - (이전에는 FAT16, FAT12 등이 있었음) 124 | 125 | 126 | > ### Q) 파일 할당 시스템도 순서대로 찾아가는 식으로 파일을 탐색, 연결리스트다 보니까 속도가 느린데 이런 부분은 파일 할당 시스템이 어떻게 해결하나요? 127 | - 메모리 캐싱을 사용하여 블록 위치를 찾는데는 빠르지만 실제 디스크 헤더가 움직이는 것은 블록이 흩어져 있으므로 여전히 느리다고 볼 수 있습니다. 128 | 129 | 130 | > ### Q) 어떤 운영체제를 사용하고 계신가요? -> 맥은 어떤 파일 시스템을 사용하나요? 131 | 맥은 APFS(Apple File System) 파일 시스템을 사용합니다. 132 | 윈도우는 FAT32, Linux는 EXT 사용 133 | 134 | ### Q) 다양한 파일 시스템 중 제일 잘 알고 있는 파일 시스템에 대해 설명해주세요. 135 | 136 | Linux 파일 시스템 Extend File System(EXT) 에 대해 설명해보겠습니다. 137 | **EXT 1** 138 | image 139 | - inode 수정을 지원하지 않으며, linked list를 통해 free block과 inode를 추적하기 때문에 성능이 저하된다는 문제점이 존재 140 | 141 | **EXT 2** 142 | image 143 | - EXT2는 부트스트랩 코드가 존재하는 부트블록과 여러 개의 블록 그룹으로 구성됩니다. 그리고 블록 그룹은 다시 6가지 영역(super block, block group descriptor, block bitmap, inode bitmap, inode table, data blocks)으로 구분됩니다. 144 | 145 | 146 | **EXT 3** 147 | - **directory 검색 성능을 높이기 위해 hash 기반 HTree 기술이 도입** 148 | - EXT2는 directory를 단순 연결 리스트로 관리 149 | - directory 내의 파일 수가 증가하는 경우 파일 검색 시간 또한 선형적으로 증가 -> **HTree 구조를 도입**하여 directory 내에 **많은 파일이 존재하더라도 상수 시간 안에 접근** 150 | - HTree란? 151 | - B-Tree와 유사하며 directory indexing을 위한 특수 트리 데이터 구조 152 | - filename의 hash를 사용하며 tree는 단일 directory entry를 가리키는 것이 아니라 directory entry들이 저장되어 있는 block을 가리킴 153 | - HTree는 최대 2 level이므로 검색은 상수 시간 안에 가능 154 | - Hash 값의 마지막 1bit는 hash collision을 나타냄 155 | - Hash collision chain의 마지막 block을 제외하고 모든 block은 collision bit가 set 되어 있음. 156 | - collision bit가 1인 경우 다음 block을 이어서 검사 157 | 158 | - **저널링(journaling) 기능 지원** 159 | - 시스템 충돌이나 정전과 같은 이벤트로 인해 발생할 수 있는 파**일시스템 손상을 신속하게 복구**하는 기능 160 | - EXT2에서 충돌이 발생하면 파일시스템 전체를 스캔 161 | - 데이터를 파일시스템의 실제 영역에 기록하기 전에 해당 정보를 log 영역에 기록하여 시스템이 갑자기 **종료**되더라도 그 **위치를 파악**할 수 있고 파일시스템 **전체를 검사할 필요 X** 162 | - EXT3는 파일시스템과 파일의 최대 크기가 작고 연속적인 데이터 블록에 대해 비효율적인 인덱싱 방식을 사용하는 등 여러 단점이 존재 163 | 164 | **EXT4** 165 | - 대용량 파일시스템과 파일 크기 지원 166 | - 1EB(=1024∗1024TB) 이상의 볼륨과 16TB 이상의 파일을 지원 167 | 168 | 169 | > ### Q) File Descriptor 에 대해 설명해주세요. 170 | 흔히 **유닉스 시스템에서 모든 것을 파일**이라고 합니다. 일반적인 정규파일부터 디렉토리, 소켓, 파이프, 블록 디바이스, 케릭터 디바이스 등 **모든 객체들을 파일로 관리**합니다. 유닉스 시스템에서 **프로세스가 이 파일들을 접근할 때 파일 디스크립터라는 개념을 이용**합니다. 171 | 즉, 유닉스에서 프로세스(process)가 파일(file)을 다룰 때 사용하는 개념으로, **프로세스에서 특정 파일에 접근할 때 사용하는 추상적인 값** 입니다. 172 | 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, **파일 디스크립터(FD)값을 이용해서 파일을 지칭**할 수 있습니다. 173 | 174 | ### Q) File Descriptor VS i-node 175 | - **파일 디스크립터 : 프로세스에서 열려 있는 파일에 대한 참조** 176 | - 운영 체제가 파일을 열 때 파일에 할당하는 고유한 식별자 177 | - 읽기/쓰기 작업에서 파일을 참조하는 데 사용되는 정수 값 178 | 179 | - **inode(인덱스 노드의 줄임말) : 디스크의 파일을 관리하는 데 사용하는 데이터 구조** 180 | - 소유자, 권한, 타임스탬프와 같은 파일이나 디렉터리에 대한 메타데이터와 구성 요소를 구성하는 디스크의 데이터 블록에 대한 포인터를 저장하는 데이터 구조 181 | - 파일 시스템에서 파일 및 디렉토리를 관리하고 디스크에 저장된 위치를 추적하는 데 사용 182 | 183 | 184 | 185 | > ### Q) i-node에 파일이 저장되는 방식에 대해 설명해주세요. 186 | 187 | 188 | image 189 | 190 | 191 | i-node는 15개의 블록으로 제한되어 있습니다. 192 | 먼저 **Direct Block에 12개의 주소만 저장**합니다. 193 | - 블록의 크기는 최대 4KB니까 파일의 공간은 48KB 밖에 되지 않지만 우리가 사용하는 모든 프로그램이나 파일은 이 크기를 넘어섭니다. 194 | - 파일의 용량이 클수록 데이터 정보를 담는 **Direct Block의 크기를 늘리면 비효율적**입니다. 195 | - 하여 이를 Single Indirect, Double Indirect, Triple Indirect로 처리합니다. 196 | 197 | 198 | 각 Indirect는 4KB의 블록인데, 여기 안에 데이터를 직접 처리하는게 아니라 **특정 블록을 접근할 수 있게 주소를 담고 있습니다.** 이러한 구조를 통해 파일은 비교적 적은 블록을 가지고 있어도 **대량의 데이터를 관리**할 수 있게 됩니다. 199 | 200 | - **Single Indirect** : 4KB / 4byte = 1024개의 데이터 주소 201 | - **Double Indirect** : Single Indirect의 주소를 1024개 202 | - 1024 x 1024 x 4KB = 4GB정도의 데이터를 접근 203 | - **Triple Indirect** : Double Indirect의 주소를 1024개 204 | 205 | > ### Q) 유닉스 아이노드 크기가 몇 바이트로 이루어져있는 지 알고 계신가요? 206 | > 💡 Hint : 64byte~128byte 로 구성 207 | 208 | 209 | Unix inode의 크기는 **일반적으로 128바이트**입니다. 210 | 이 크기는 **필수 메타데이터를 저장하기에 충분한 공간을 허용하기 때문**입니다. 메모리 사용량 및 디스크 공간의 제약과 함께 **메타데이터에 대한 빠른 접근과 저장공간의 균형을 맞추기 위해 선택**되었습니다. 211 | - inode 크기 212 | - 작을수록 213 | - 더 많은 파일을 디스크 파티션에 저장 214 | - 또 너무 작으면 아이노드 정보를 저장할 수 없음 215 | - 클수록 216 | - 더 많은 공간을 차지 217 | - inode 자체를 저장하는 데 더 많은 공간이 필요하기 때문에 시스템 속도가 느려질 수 있음 -> 즉, 실제 파일을 저장하는 데 사용할 수 있는 공간이 더 적음 218 | 219 | 그러나 **일부 파일 시스템은** 추가 메타데이터 또는 확장 속성을 수용하기 위해 256바이트 또는 512바이트와 같은 **더 큰 크기를 사용**할 수 있습니다. 220 | 221 | 222 | 223 | > ### Q) 섹터 단위가 512byte인데 파일이 412byte라 100byte가 남으면 어떤 문제가 발생하나요? 224 | > 💡 hint : 단편화! 내부단편화/외부단편화 225 | 226 | ![image](https://user-images.githubusercontent.com/67494004/227765035-b65d822d-d71d-458b-b59c-97477a06482e.png) 227 | 228 | **내부 단편화**는 파일에 **필요한 것보다 더 많은 공간이 할당**되어 **파일 자체 내에서 공간이 낭비**될 때 발생합니다. 이 경우 파일은 412바이트에 불과하지만 512바이트의 전체 섹터가 할당됩니다. 즉, 파일 내에 **100바이트의 내부 단편화**가 있음을 의미합니다. 229 | 230 | ![image](https://user-images.githubusercontent.com/67494004/227765016-34f3bdfa-cf8d-47b8-ae29-c827e699dad1.png) 231 | 232 | **외부 단편화**는남아있는 총 메모리 공간이 요청한 메모리 공간보다 크지만, **남아있는 공간이 연속적(contiguous)이지 않아 발생하는 현상** 입니다. 이 경우 412바이트 파일이 포함된 섹터에는 **100바이트의 사용되지 않은 공간**이 있으며, **새 파일을 저장하는 데** 사용할 수 있는 연속 여유 **섹터가 충분하지 않은 경우 외부 단편화에 기여**할 수 있습니다. 233 | 234 | 시간이 지남에 따라 내부 및 외부 단편화로 인해 운영 체제가 새 파일을 저장할 연속 **여유 공간 블록을 찾기 어려워져 성능이 저하되고 디스크 공간이 낭비**될 수 있습니다. **단편화를 최소화**하기 위해 파일 시스템은 종종 클러스터링 및 **블록 할당 알고리즘**과 같은 기술을 사용하여 공간을 보다 효율적으로 할당하고 낭비되는 공간을 줄입니다. 235 | 236 | 이미지 및 내용 참고 237 | https://code-lab1.tistory.com/54 238 | https://velog.io/@codemcd/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9COS-18.-%ED%8C%8C%EC%9D%BC-%ED%95%A0%EB%8B%B9 239 | -------------------------------------------------------------------------------- /Operating System/Interrupt.md: -------------------------------------------------------------------------------- 1 | ### 인터럽트는 언제 발생돼서 어떻게 처리하나요? 2 | - 인터럽트는 **컴퓨터 파워에 이상이 있거나 하드웨어 디바이스로인한 인터럽트,프로세스 오류등**으로 발생합니다. 3 | 인터럽트 요청이 들어오면 일시중단하고 현재 프로그램상태를 보존하고 인터럽트를 요청한 장치와 원인을 파악하고 작업을 수행합니다. 그후, 인터럽트 발생시 저장해둔 PC를 다시 복구해서 재개합니다. 4 | 작업을끝내고나면 OS에 정의되어있는 인터럽트 핸들러를 실행합니다. 인터럽트 핸들러로 I/O를 대기중인 프로세스를 꺠우거나 깨어난 프로세스가 작업을 계속할수있도록 할수 있습니다. 5 | 6 | #### Q) 시스템콜이 들어오면 운영체제에서 어떤 과정을 통해 실행되나요? 7 | - 유저모드에서 수행되던 작업중 write()라는 시스템콜이 발생하면 현재 어떤모드인지 구분하는 모드비트를 1에서 0으로변경하고 커널모드에서 write()를 실행하고 실행이완료되면 모드비트를 다시 1로 변경하고 유저모드로 돌아갑니다. 8 | 9 | #### Q) 인터럽트와 시스템콜 각각이 발생할수있는 상황 예시를 들어주세요 10 | - 시스템콜 : 인텔리제이 같은 개발도구에서 콘솔에 hello를 출력하고자 할때 모니터에 hello를 출력하기위해 write() 시스템콜을 호출하게 되어 발생할수있습니다. 11 | - 인터럽트 : 컴퓨터 파워에이상이있거나 존재하지않는 메모리주소에 접근한다던지, 0으로 나누는연산을 실행하는경우 발생할수있습니다. 12 | 13 | > #### Q) 사용하는 프로그래밍언어에서 시스템콜을 어떻게 사용하는지 알고계신게 있나요? 14 | - JAVA에서 파일을읽는 read를 사용하는경우 운영체제의 기능이 구현된 C나 C++로 만들어진 함수가 실행됩니다. 이때 시스템콜이 발생하고 커널모드로 진입하게되고 15 | 디스크 컨트롤러를 거쳐 커널버퍼, JVM버퍼를 복사하는등의 과정을거쳐 운영체제의 기능이 실행됩니다. JVM -> JNI -> 시스템콜 -> 커널 -> 디스크컨트롤러 -> 버퍼복사 ... 16 | 17 | > #### Q) JNI가 무엇인지 설명해주세요 18 | - JVM이 특정 OS환경에 종속되지않은 상태로 운영체제의 기능을 담고있는데 일부 운영체제의 기능을 담지는 못했기때문에 자바언어로 해결이 안되는경우 **운영체제의 Native기능을 C나 C++로 만들어논 함수를 자바 메서드와 연결해주는 역할**을합니다. 19 | 20 | #### Q) 하드웨어/ 소프트웨어 인터럽트에대해 설명해주세요 21 | - 소프트웨어 인터럽트는 CPU내부에서 사용자가 실행할때 명령관련 모듈이 변화하는경우 발생합니다. 0으로 나누는 연산을 한다던지, 예외가발생한다던지, 존재하지않는 메모리 주소에 접근할때 발생합니다. 22 | 23 | - 하드웨어 인터럽트는 CPU외부에서 요구되고 , 운영체제의 처리가 필요한 상황을 전기적인신호를 사용해 알리기위해 발생합니다. 컴퓨터 파워에 이상이 있거나 하드웨어 디바이스로인한 인터럽트 등으로 발생합니다. 24 | 25 | > #### Q) 인터럽트 벡터/핸들러에대해 설명해주세요 26 | - 인터럽트 벡터 : 인터럽트를 요구한 I/O장치의 식별번호 , 해당 장치를위한 인터럽트처리 루틴의 시작주소를 찾는데 사용된다. 27 | - 인터럽트 핸들러 : 실제 인터럽트를 처리하기위한 루틴으로 인터럽트 서비스 루틴이라고도 한다(ISR) , 인터럽트별로 처리해야할 내용들이 프로그램되어있다. 28 | 29 | > #### Q) 소프트웨어 인터럽트를 처리하는 3가지 방법 30 | - Trap : 의도적으로 발생하는 상황, 대표적으로 시스템 콜 사용할때 발생하는 경우가 있다. 트랩 발생후 제어를 다음 명령으로 넘긴다. 31 | - Fault : **핸들러가 정정할수있을 가능성이 있는 일**로 발생한다. 대표적인예로 페이지가 없는 경우 발생하는 page fault. fault 발생후 오류 핸들러로 제어를 넘긴다. 32 | => 핸들러가 에러를 정정할수있으면 제어를 오류를 발생시킨 명령으로 돌려서 재실행한다. 33 | - 중단 : 하드웨어 오류와같이 **복구불가능한 치명적인 에러에서 발생**한다. 대표적인예로 0으로 나누는 경우가 있다. 응용프로그램으로 제어를 리턴하지않고 종료하는 중단루틴으로 반환한다. 34 | 35 | > #### Q) 인터럽트를 처리하는도중 또다른 인터럽트가 발생한다면 어떻게 처리되는지 설명해주세요 36 | 인터럽트를 처리하는도중 또다른 인터럽트가 발생할수있는데 이때 두가지 처리방법이있습니다. 37 | - 첫번째 **인터럽트 핸들러를 실행하고있는도중엔 다른 인터럽트를 수행하지않도록 하는 방법** . 이경우엔 새로 발생한 인터럽트는 대기상태로있다가 CPU 가 다시 인터럽트 가능한상태로 바뀐후에 인식됩니다 38 | - 두번째방법은 **인터럽트들간에 우선순위를 정하고 우선순위가 낮은 인터럽트를 처리하는동안 우선순위가 높은 인터럽트가 들어오면 새로운 인터럽트를 처리하는 방법**이있습니다. 39 | 40 | 원칙적으로는 여러 인터럽트가 발생했을때 데이터 일관성을 유지하기위해 첫번째방법을 사용하지만 두번째방법을 사용하는경우도 있습니다. 41 | 42 | 43 | #### Q) 유저모드와 커널모드에대해 아는대로 설명해주세요 44 | 유저모드와 커널모드로 나눈이유는 유저프로그램과 커널을 분리시키기 위해서 입니다. 분리시키는 이유는 첫번째로 **유저프로그램은 파일을 읽는다거나 프로세스가 생성되는 내부동작을 신경쓸 필요없기때문**입니다.두번째로는 **보안이 강화**됩니다. 신뢰할수없는 유저가 운영체제의 서비스를 쉽게 조작하는걸 방지할수있습니다. 45 | - 유저모드 : 사용자 애플리케이션 코드가 실행되고, 하드웨어를 직접 접근할수없습니다. 시스템 서비스를 호출하면 유저모드에서 커널모드로 전환됩니다. 46 | - 커널모드 : 모든 CPU명령을 실행할수있고 , 운영체제의 서비스나 디바이스 드라이버같은 커널모드코드를 실행합니다. 47 | 48 | > #### Q) 유저모드에서 시스템콜 이외의 경우에 커널모드로 변환되는 사례 49 | - 인터럽트 : 현재 작업실행을 중지하고 커널모드로 전환해서 인터럽트 서비스루틴으로 제어가 넘어가는 경우 50 | - DMA : DMA를 사용하면 하드웨어 장치가 CPU를 사용하지 않고 시스템 메모리에 직접 액세스할 수 있습니다. DMA 전송이 시작되면 CPU는 커널모드로 전환하여 전송을 수행하게 됩니다. 51 | 52 | #### Q) 폴링이 뭔지 설명해주세요 53 | - 운영체제가 하드웨어 장치의 상태레지스터를 읽음으로써 명령의 수신여부를 주기적으로 확인하는것.레지스터에 데이터를 전달하고 명령레지스터에는 명령을 기록하고 하드웨어 장치가 특정 동작을 처리했는지 폴링 반복문을 돌면서 기다리게된다(성공/실패코드를 받게된다). 하드웨어가 간단하지만 검사하는데 걸리는시간이 많이걸린다는 단점이있다. 54 | 55 | > #### Q) 폴링, 인터럽트중 어떤것이 더 신속하게 대응할수있는지? 56 | - 폴링은 특정 주기마다 응답을 확인하기때문에 **정확한 타이밍에 대응할수있다는 보장이 없으며**, 인터럽트는 인터럽트 장치에 신호가 들어오는 **즉시 발동**되기때문에 폴링보다 신속하게 대응할수있다. 57 | 58 | 59 | #### Q) DMA가 생기게 된 이유, 어떻게 동작하는지 설명해주세요 60 | - 기억장치와 I/O 장치간의 데이터이동에 반드시 CPU를 경유해야하기때문에 큰 데이터블록을 전송하는경우 인터럽트과정이 무수히 많아질수있어 CPU가 효율적으로 작동할수 없을수 있습니다. 예를들어 I/O를 write하는경우 CPU가 주 기억장치로부터 데이터를 한개씩 읽어 내부레지스터에 적재한다음 I/O장치로 보내고, I/O 명령도 보내야하는 일이 반복됩니다.이러한 문제를 해결하기위해 CPU의 개입없이 I/O장치와 기억장치 사이에 데이터 전송을 수행할수있는 DMA가 등장합니다. 61 | 62 | - **한마디로 인터럽트의 오버헤드를 줄이기위해 등장했습니다.** 63 | 64 | - 운영체제가 DMA엔진에 메모리상의 데이터위치와 전송할 데이터의 크기와 대상장치를 프로그램해서 CPU가 다른일을 진행할수있도록 합니다. 65 | CPU가 DMA컨트롤러에게 명령을 보내면 CPU로 버스요청을 보내고, CPU는 DMA 컨트롤러에게 버스승인 신호를 보냅니다. 그러면 DMA컨트롤러가 버스를 사용해 주기억장치로부터 데이터를 읽어서 디스크에 저장합니다. 저장할 데이터가 남아있지 않을때까지 이 과정을 반복합니다. 66 | 67 | 68 | > #### Q) 큰 데이터를 보낼떄만 DMA를 사용하나요? 작은데이터를 DMA로 보냈을떄 성능상 문제는없나요? 69 | - 해당 데이터에서 복사해야될 I/O 블록의 크기, DMA컨트롤러, 메모리 동기화 같은 기타 작업수행이 포함되는 비용 등을 고려해봐야합니다. 전송되는 데이터 양에비해 DMA전송 설정의 오버헤드가 더 크다면 CPU를 사용해 데이터를 직접 복사하는것이 더 효율적일수있습니다. 70 | 71 | #### Q) 서로다른 시스템콜을 어떻게 구분할수있나요? 72 | - **커널에서 내부적으로 시스템콜별로 고유번호를 할당**하고 read() 시스템콜이 호출되면 read()의 고유번호에 해당하는 제어루틴을 커널내부에 정의해두었고 커널이 그 번호를 확인후 호출합니다. 73 | 74 | 75 | 76 | #### 사진,내용에 대한 출처 77 | - https://www.tutorialspoint.com/operating_system/os_io_hardware.htm DMA, 폴링/ 인터럽트 78 | -------------------------------------------------------------------------------- /Operating System/Page Replacement Algorithm.md: -------------------------------------------------------------------------------- 1 | #### Q-1) 페이지 교체 알고리즘에 대해 설명해주세요. 2 | 3 | - `프로세스가 요구한 페이지가 현재 메모리에 없으면 페이지 부재가 발생`합니다. 페이지 부재가 발생하면 스왑 영역에서 페이지를 메모리로 가져오는데 만약 메모리가 꽉 찼다면 메모리에 있는 페이지를 스왑영역으로 보내야 합니다. 이때 페이지 교체 알고리즘은 `스왑 영역으로 보낼 페이지를 결정하는 알고리즘`으로, 메모리에서 앞으로 사용할 가능성이 적은 페이지를 대상 페이지로 선정하여 `페이지 부재를 줄이고 시스템의 성능`을 향상합니다. 4 | 5 | #### Q-2) 현대에 가장 많이 사용되는 페이지 교체 알고리즘에 대해 설명해주세요. 6 | 7 | - `NUR 페이지 교체 알고리즘`은 최근 미사용 페이지 교체 알고리즘이라고 불리며 LRU, LFU 페이지 교체 알고리즘 성능이 비슷하면서도 불필요한 공간 낭비 문제를 해결한 알고리즘입니다. 8 | `추가 비트 2개`만 사용하여 예측한다는 특징이 있습니다. 따라서 페이지마다 `참조 비트`와 `변경 비트`를 가지므로 페이지마다 추가되는 `메모리 공간이 2비트`뿐입니다. 여기서 `참조 비트는 PTE 접근 비트를 가리키고, 변경 비트는 PTE의 변경 비트`를 가리킵니다. 참조 비트와 변경 비트는 초깃값이 0이며 다음과 같은 경우 1이 됩니다. 9 | 10 | 1. 참조 비트: 페이지에 접근(read/execute)하면 1이 된다. 11 | 2. 변경 비트: 페이지가 변경(write/append)되면 1이 된다. 12 | 13 | 모든 페이지의 초기 상태는 (0,0)입니다. 이 상태에서 페이지에 읽기 또는 실행과 같은 '접근'이 발생하면 (1,0)으로 바뀐다. 만약 페이지에 쓰기 또는 추가 같은 '변경'이 일어나면 (0,1)이 된다. 또한 접근과 변경, 두 가지 연산이 다 발생하면 (1,1)이 됩니다. 14 | 15 | NUR 페이지 교체 알고리즘에서 대상 페이지(victim page)를 선정할 때는 (0,0), (0,1), (1,0), (1,1) 중에서 하나를 고르는데, 가장 먼저 (0,0)인 페이지를 선정한다. 즉 접근한 적도 변경한 적도 없는 페이지를 스왑 영역으로 옮긴다. 만약 (0,0)인 페이지가 없다면 (0,1)인 페이지를, (0,1)인 페이지가 없다면 (1,0)인 페이지를 (1,0)인 페이지가 없다면 최종적으로 (1,1)인 페이지를 스왑 영역으로 옮깁니다. 16 | 17 | 위에서부터 아래로 대상 프레임(victim page) 우선순위가 낮아진다. 만약 모두 (1,1)이면 초기화를 하도록 한다. 18 | 19 | syn_async 20 | 21 | 최적 근접 알고리즘인 LRU, LFU, NUR 페이지 교체 알고리즘의 성능은 거의 비슷하며 FIFO 페이지 교체 알고리즘보다 우수하다. 이 중에서 `NUR 페이지 교체 알고리즘은 2bit만 추가하여 다른 알고리즘과 유사한 성능을 낼 뿐만 아니라 쉽게 구현할 수 있다는 장점` 덕분에 가장 많이 사용되고 있다. 22 | 23 | #### Q-3) FIFO 알고리즘 문제점은 뭐가 있을까요? 24 | 25 | - 먼저 FIFO 페이지 교체 알고리즘은 시간상으로 메모리에 가장 먼저 들어온 페이지를 대상 페이지로 선정하여 스왑 영역으로 쫒아냅니다. 26 | 27 | syn_async 28 | 29 | FIFO 페이지 교체 알고리즘은 큐로 구현합니다. 메모리의 맨 위에 있는 페이지는 가장 오래된 페이지이고, 새로운 페이지는 항상 맨 아래에 삽입됩니다. 30 | 31 | 메모리에 먼저 올라왔어도 자수 사용되는 페이지가 있기도 하고, 나중에 올라왔어도 한 번만 사용되는 페이지가 있기도 하다. `FIFO 페이지 교체 알고리즘은 무조건 오래된 페이지를 대상 페이지(victim page)로 선정하기 때문에 성능이 떨어지는데` 이러한 문제점을 개선한 것이 2차 기회 페이지 교체 알고리즘(second chance replacement algorithm)입니다. 32 | 33 | #### Q-4) 사용가능한 프레임수가 증가하면 페이지 폴트가 줄어들까요? 34 | 35 | - syn_async 36 | 37 | 위의 표는 위키피디아에서 참조한 것으로, 실제 예시를 통하여 확인할 수 있습니다. 직관적으로 말이 전혀 되지 않아보이지만, 아래의 사례를 통하여 이런 사례가 존재한다는 것을 알 수 있습니다. 3개의 page frames을 사용하는 경우에 4개의 page frames 을 사용하는 것보다 더 적은 page fault가 발생합니다. 38 | 39 | `Belady의 역설`은 일반적으로 FIFO (선입 선출) 페이지 교체 알고리즘을 사용할 때 발생하고, LRU (Least Recently Used) 와 같은 알고리즘에서는 페이지 프레임이 증가함에 따라 페이지 폴트가 감소한다고 합니다. 40 | 41 | #### Q-5) LRU 알고리즘은 어떤 자료구조를 사용해서 구현할 수 있을까요? 42 | 43 | - LRU 페이지 교체 알고리즘(Latest Recently Used page replacement algorithm)은 '`최근 최소 사용 페이지 교체 알고리즘`'이라고도 합니다. 즉 최근에 사용된 페이지는 놔두고 오래전에 사용된 페이지를 대상 페이지(victim page)로 선정합니다. 44 | 45 | `큐로 구현가능`하며 사용한 데이터를 큐에서 제거하여 맨 위로다시 올리고, 프레임이 모자랄 경우 맨 아래에 있는 데이터를 삭제합니다. 46 | `단점으로는 프로세스가 주기억장치에 접근할때마다 참조된 페이지 시간을 기록해야 하므로 막대한 오버헤드가 발생 카운터나 큐, 스택과 같은 별도의 하드웨어가 필요`합니다. 47 | 48 | #### Q-6) 그럼 큐를 어떻게 구현할까요 하드웨어 쪽으로 LRU 알고리즘으로 구현할 때 페이지 변경 여부를 알 수 있는 특정 비트를 둔다고 한다. 비트를 변경하고 변경여부를 확인가능, 참조여부 49 | 50 | - `페이지 접근 시간에 기반한 구현`, 가장 간단한 형태는 페이지에 접근한 시간을 기록하여 구현하는 것이다. 51 | syn_async 52 | 53 | FIFO 페이지 교체 알고리즘이 메모리에 올라온 시간을 기준으로 가장 오래된 페이지를 교체한다면, LRU 페이지 교체 알고리즘은 페이지에 접근한 지 가장 오래된 페이지를 교체한다. 54 | 55 | 주의할 점은 메모리 접근 패턴을 변경하면 LRU 페이지 교체 알고리즘의 성능이 FIFO 페이지 교체 알고리즘만큼 느려지기도 하고 최적 페이지 교체 알고리즘만큼 좋아지기도 한다는 사실이다. 일반적으로 LRU 페이지 교체 알고리즘의 선능은 FIFO 페이지 교체 알고리즘보다 우수하고 최적 페이지 교체 알고리즘보다는 조금 떨어진 것으로 알려져 있다. 56 | 57 | `카운터에 기반한 구현`, 페이지 접근 시간을 기록하여 구현할 수 도 있지만 카운터를 사용하여 구현할 수 있다. 그런데 접근 시간을 기록하든 카운트를 기록하든 두 방법은 모두 추가적인 메모리 공간을 필요로 하는 것이 단점이다. 가령, 0~1024초를 표시하려면 10bit가 필요하고 더 큰 숫자를 표시하려면 더 많은 비트를 사용해야한다는 것이다. 이러한 추가 공간으로 인해 사용자가 사용할 수 있는 공간이 낭비된다. 58 | 59 | `참조 비트 쉬프트 방식`, 각 페이지에 일정 크기의 참조 비트를 만들어 사용한다. 참조 비트의 초깃값은 0이며 페이지에 접근할 때마다 1로 바뀐다. 또한 참조 비트는 주기적으로 오른쪽으로 한 칸씩 이동한다. 60 | 61 | 참조 비트 쉬프트 방식은 LFU 페이지 교체 알고리즘과 혼동되기도 한다. LFU 페이지 교체 알고리즘은 페이지의 접근 횟수를 측정하여 대상 페이지를 선정한다. 62 | 63 | syn_async 64 | 65 | #### Q-7) LRU, LFU 이상적인 페이지 교체 알고리즘에 도달하기 위해 나온걸로 아는데 그 알고리즘에 대해 설명하시오. 66 | 67 | - `최적 페이지 교체 알고리즘`(Optimal page replacement algorithm)은 앞으로 사용하지 않을 페이지를 스왑 영역으로 옮긴다. 메모리가 앞으로 사용할 페이지를 미리 살펴보고 페이지 교체 선정 시점부터 사용 시점까지 가장 멀리 있는 페이지를 대상 페이지로 선정한다. 즉, 프레임에 있는 페이지가 가장 나중에 불리는 것을 대상 페이지로 선정하는 것이다. 68 | syn_async 69 | 70 | `최적 페이지 교체 알고리즘은 미래의 메모리 접근 패턴을 보고 대상 페이지를 결정하기 때문에 성능이 좋다.` 하지만 미래의 접근 패턴을 안다는 것이 불가능하여 실제로 구현할 수 없다. 최적 페이지 교체 알고리즘에 근접하는 방법을 연구한 결과 최근 최소 사용 알고리즘인 LRU(Latest Recently Used)와 최소 빈도 사용 알고리즘인 LFU(Latest Frequently Used), 최근 미사용 알고리즘인 NUR(Not Used Recently) 등이 개발되었다. 이러한 알고리즘은 과거의 데이터를 바탕으로 미래의 접근 패턴을 추정하기 때문에 최적 근접 알고리즘(Optimal approximation algorithm)이라고 부른다. 71 | 72 | #### Q-8) 최적 알고리즘 73 | 74 | #### Q-9) 페이징 교체가 일어날 수 있는 상황에 대해 설명 75 | 76 | - 페이지 교체 알고리즘은 `가상 메모리 관리`에서 사용됩니다. 운영 체제는 일반적으로 사용자가 실행하는 프로그램에 할당된 가상 주소 공간을 물리적인 메모리 공간에 매핑합니다. 그러나 물리적인 메모리 공간은 제한적이므로 운영 체제는 가상 주소 공간 중 일부만을 메모리에 올려놓고, 나머지는 디스크에 저장합니다. 이때, 프로그램이 필요로 하는 페이지가 메모리에 없는 경우 `페이지 부재`(page fault)가 발생합니다. 페이지 부재가 발생하면 운영 체제는 디스크에서 해당 페이지를 읽어와 메모리에 올리는데, 이때 페이지 교체 알고리즘이 사용됩니다. 페이지 교체 알고리즘은 어떤 페이지를 디스크로 쫓아낼 것인지 결정하여 새로운 페이지를 메모리에 올리는 역할을 수행합니다. 페이지 교체 알고리즘의 목표는 `페이지 부재가 최소화`되도록 하는 것입니다. 77 | 78 | #### Q-10) 더티 비트는 어느 상황에 사용하는지? 79 | 80 | - `페이지 교체 알고리즘은 페이지 부재(page fault)가 발생`했을 때, 메모리에 적재된 페이지 중에서 어떤 페이지를 디스크로 쫓아낼지 결정합니다. 이때, `메모리에 적재된 페이지가 디스크의 내용과 달라져서 디스크의 내용을 갱신`해야 하는 경우가 있습니다. 이를 더티 페이지(dirty page)라고 합니다. 더티 비트는 이러한 더티 페이지를 추적하기 위해 사용됩니다. 더티 비트는 페이지 테이블에 존재하며, 각 페이지마다 해당 비트가 할당됩니다. 페이지가 갱신되면, 더티 비트가 설정되어 해당 페이지가 더티 페이지임을 표시합니다. 이를 통해 페이지 교체 알고리즘은 더티 페이지가 있는 페이지를 우선적으로 디스크로 쫓아내어 디스크의 내용을 갱신할 수 있습니다. 즉, `더티 비트는 페이지 교체 알고리즘이 페이지 교체를 수행할 때 더티 페이지를 우선적으로 쫓아내어 디스크의 내용을 갱신하도록 돕는 기술`입니다. 81 | -------------------------------------------------------------------------------- /Operating System/Paging & Segmentation.md: -------------------------------------------------------------------------------- 1 | # Paging & Segmentation 2 | 3 | ### Paging & Segmentation에 대해 설명해주세요 4 | - * 둘 다 가상 메모리를 관리하는 기법입니다. 5 | 페이징은 프로세스를 일정한 크기의 페이지로 분할해서 메모리에 적재하는 방식입니다. 6 | 세그멘테이션은 가상 메모리를 서로 크기가 다른 논리적 단위로 분할한 것을 의미합니다. 세그멘테이션은 프로세스를 물리적 단위인 페이지가 아닌 논리적 단위인 세그먼트로 분할해서 메모리에 적재하는 방식입니다. 7 | 8 | ### Q) 세그먼트의 크기를 나누는 기준은 무엇인가요? 9 | - 사용자 관점으로 메모리의 크기를 나누고, 지원합니다. 반면 페이징 기법은 하드웨어에 의해 분리된 하나의 주소를 페이지 번호와 페이지 간격으로 크기를 특정합니다. 10 | 11 | ### Q) 페이징에 비해 외부단편화가 많이 일어날 것 같습니다. 현재에는 이를 어떻게 해결하고 있을까요? 12 | - 압축 ( Compaction ) 기법을 사용합니다. 압축 기법은 주기억장치 내 분산되어 있는 단편화된 공간들을 통합하여 하나의 커다란 빈 공간을 만드는 작업을 의미합니다. 13 | - <외부단편화가 발생한 상황> 14 | ![image](https://user-images.githubusercontent.com/76711238/229358437-ec2fcee5-8e25-44dd-92c3-a15f800a874e.png) 15 | - <빈 공간을 하나의 연속된 공간으로 만드는 과정(압축)> 16 | ![image](https://user-images.githubusercontent.com/76711238/229358459-96821116-2c8b-4a4d-821f-fc62e949435a.png) 17 | 18 | ### Q) 페이징 사용 시 외부 및 내부 단편화 문제에 대해 설명해주세요. 19 | - 페이징 : 내부 단편화 발생합니다(페이지 내부 메모리 낭비). 반면 외부 단편화는 발생하지 않습니다.(비연속적 할당) 20 | 21 | > Q-1) 페이징 사용 시 내부 단편화가 일어날 수 있는 최대 크기는 무엇일까요? 22 | - 페이징을 통해 마지막 페이지는 최대 페이지 크기 -1 만큼 메모리가 버려지게 됩니다. 23 | 24 | > ### Q) 세그멘테이션을 위해서 세그멘트 단위 별로 가지고 있는 레지스터에 대해 설명해주세요. 25 | - 세그먼트 레지스터 (Segment Register)는 세그먼트 메모리의 한 영역에 대한 주소지정을 제공합니다. 26 | 27 | 이름|레지스터의 기능 28 | -- | -- 29 | CS | 코드 세그먼트의 시작 주소를 가리킵니다. CS레지스터는 프로그램의 코드 세그먼트의 시작 주소를 포함합니다. 이 세그먼트 주소에 명령어 포인터(instruction pointer, IP) 레지스터의 오프셋 값을 더하면, 실행하기 위해 메모리로부터 가져와야 할 명령어의 주소가 됩니다. 30 | DS | 프로그램에 정의된 데이터 세그먼트의 시작 주소를 가리킵니다. 데이터의 오프셋을 DS 레지스터에 저장된 주소 값에 더해 데이터 세그먼트 내에 위치해 있는 데이터의 주소를 참조합니다. 31 | SS | 실행 과정에서 필요한 데이터나 연산 결과 등을 임시로 저장하거나 삭제할 때 사용하는 스택 세그먼트의 시작 주소를 가리킵니다. 메모리 상에 스택의 구현을 가능하게 합니다. 32 | ES | 추가로 사용된 데이터 세그먼트의 주소를 가리킵니다. 메모리 주소지정을 다루는 스트링(문자 데이터) 연산에서 사용됩니다. 33 | FS/GS | 기억장소 요구사항을 다루기 위해서 80386에서 추가로 도입된 여분의 세그먼트 레지스터입니다. 34 | 35 | 36 | ### Q) 페이지 크기에 따른 성능에 대해서 설명해주세요. 37 | - 페이지 크기가 작다면 38 | - 내부단편화가 줄어듭니다. 39 | - 페이지 크기가 작을수록 resolution(해당 메모리에 필요한 데이터가 있는 확률)을 높일 수 있습니다. 만약 페이지 크기가 크면 다른 필요없는 부분이 있을 확률이 크기 때문입니다. 40 | 41 | - 페이지 크기가 크다면 42 | - 페이지 개수가 줄어들기 때문에 그만큼 페이지 테이블 크기도 줄어듭니다. 43 | - Page fault 발생 확률을 줄이려면 페이지 크기가 큰 것이 좋습니다. 이는 지역성과도 관련이 있는데, 대부분 프로세스는 필요한 부분이 일정 범위 이내인 경우가 많으므로 페이지 크기가 클수록 필요한 부분이 있을 확률이 크기 때문입니다. 44 | 45 | ![image](https://user-images.githubusercontent.com/76711238/229358856-680efeb3-2698-4a1a-8bc9-80d471d60e0d.png) 46 | 47 | ### Q) 주소공간이 존재할 때, 주소 공간이 수정 가능한 지 페이지 테이블을 사용해서 알 수 있는 방법을 설명해주세요. 48 | - 페이지 테이블 내부의 R/W/X 비트를 사용해서 수정/읽기/작성 권한을 확인할 수 있습니다. 49 | ![image](https://user-images.githubusercontent.com/76711238/229357591-9a2c9d0f-a91b-4621-ad93-f4d416f3e99e.png) 50 | 51 | ### Q) 페이지 테이블서의 인덱스 필드가 어떻게 결정되는지 설명해주세요. 52 | - 각 메모리의 크기에 비례해서 인덱스 필드의 크기 또한 유동적으로 바뀝니다. 53 | 54 | ### Q) PAGE FAULT 발생 과정 55 | - PAGE FAULT : 프로세스가 페이지를 요청했을 때 그 페이지가 main 메모리에 없는 상황을 의미합니다. 56 | 57 | 단계|과정 58 | -- | -- 59 | 1 | CPU가 가상 주소를 MMU에게 요청합니다. 60 | 2 | MMU는 먼저 TLB로 가서 그 가상주소에 대한 물리주소가 캐싱돼 있는지 확인합니다. 61 | 3 | TLB에 캐싱된 물리주소가 62 | 3-1 |- 있으면 MMU가 해당 페이지의 물리 주소로 데이터를 갖고 와서 CPU에게 보냅니다. 63 | 3-2 |- 없으면 MMU가 CR3 레지스터를 가지고 물리 메모리에 해당 프로세스의 페이지 테이블에 접근합니다. 64 | 4 | MMU가 페이지 테이블에서 물리주소가 있는지 valid bit를 확인합니다. 65 | 5 | valid bit의 값이 66 | 5-1 |- 1이면 MMU가 해당 페이지의 물리 주소로 데이터를 갖고 와서 CPU에게 보냅니다. 67 | 5-2 |- 0이면 MMU가 페이지 폴트 인터럽트를 운영체제에 발생시킵니다. 68 | 6 | 운영체제는 해당 페이지를 저장공간에서 가져옵니다. 69 | 7 | 운영체제는 저장공간에서 가져온 데이터를 메모리에 올려주고, 페이지 테이블을 업데이트 해줍니다. valid bit -> 1, 물리주소를 업데이트합니다. 70 | 8 | 운영체제는 CPU에게 프로세스를 다시 실행하라고 합니다. (PCB 저장 정보 기반으로) 71 | 9 | CPU는 다시 MMU에 가상 주소를 요청합니다. 72 | 73 | ### Q) 처음에 어떻게 필요한 페이지만 메모리에 올릴까요? 74 | - Demand paging을 사용해서 메모리에 올리게 됩니다. 이는 요구된 page만을 메인 메모리에 적재합니다. 이를 통해 사용되지 않는 page를 메모리에 적재하는 것을 예방하고 교체시간, 메모리 공간을 절약합니다. 75 | 76 | 77 | #### 사진 & 내용 출처 78 | https://hajunyoo.oopy.io/a91edd96-2b39-4a3a-ab25-d5b3504a6f0d#af9aee77-2305-4080-a1b6-3a1194190736 79 | 80 | https://velog.io/@jsb100800/CS-%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC 81 | 82 | https://eunjinii.tistory.com/142 83 | 84 | https://code-lab1.tistory.com/54 85 | 86 | https://dhhd-goldmilk777.tistory.com/41 87 | -------------------------------------------------------------------------------- /Operating System/Synchronous & Asynchronous & blocking & nonblocking.md: -------------------------------------------------------------------------------- 1 | # Synchronous x Asynchronous & blocking x non-bloking 2 | 3 | ### Q) 동기, 비동기, 블락킹, 논블락킹에 대해 간략히 설명해주세요. 4 | 5 | - 동기 6 | 7 | - 여러 작업들을 순차적으로 실행합니다. 8 | 9 | - 비동기 10 | - 여러 작업들을 독립적으로 실행합니다. 11 | 12 | syn_async 13 | 14 | - blocking 15 | - 작업을 요청한 프로세스/스레드는 요청이 완료될 때까지 블락됩니다. 16 | syn_async 17 | - non-blocking 18 | - 프로세스, 스레드를 블락시키지 않고 요청에 대한 현재 상태를 즉시 반환합니다. 19 | syn_async 20 | 21 | > ### Q) 비동기처리를 하는 예시를 들어주세요. 22 | 23 | - 비동기 처리의 대표적인 예시는 자바스크립트의 setTimeout같은 웹 API가 있습니다. 24 | 25 | ```jsx 26 | setTimeout(() => { 27 | console.log("1번"); 28 | }, 5000); 29 | setTimeout(() => { 30 | console.log("2번"); 31 | }, 3000); 32 | setTimeout(() => { 33 | console.log("3번"); 34 | }, 1000); 35 | console.log("4번"); 36 | // 4번->(1초)->3번->(2초)->2번->(2초)->1번 37 | ``` 38 | 39 | 적힌 순서대로 1번 2번 3번 4번으로 될 것 같지만, `setTimeout`은 비동기 함수이기 때문에 완전히 다른 결과가 나오게 됩니다. 40 | `setTimeout`이 만약 동기적으로 처리됐다면 5초뒤 1번이, 3초뒤 2번이, 1초뒤 호출되어 총 8초가 걸렸겠지만,비동기적으로 처리됐기 때문에 전체 걸린 시간은 5초가 된 것입니다. 41 | 42 | #### Q) Java에서도 비동기처리를 하는 예시를 들어주세요. 43 | 44 | - #### execute 45 | 46 | - runnable 인터페이스 필요, result값 설정 가능 47 | - runnable - 객체를 리턴하지 않음, exception 발생시키지 않음 48 | 고로, 객체를 리턴할 필요가 없을 때 사용한다. 49 | - shutdown() 걸어줘야 함. 50 | 51 | exit 우선 출력 52 | 2초 후 Hello 출력 53 | 54 | ```java 55 | public class FutureEx { 56 | public static void main(String[] args) { 57 | ExecutorService es = Executors.newCachedThreadPool(); 58 | es.execute(() -> { 59 | try { 60 | Thread.sleep(2000); //interrupt 발생시 exception 던질 수 있도록 61 | } catch (InterruptedException e) { 62 | e.printStackTrace(); 63 | } 64 | log.info("Hello"); 65 | }); 66 | log.info("Exit"); 67 | } 68 | } 69 | 70 | ``` 71 | 72 | ``` 73 | [main] INFO com.example.demo.FutureEx - Exit 74 | [pool-1-thread-1] INFO com.example.demo.FutureEx - Hello 75 | ``` 76 | 77 | - #### submit 78 | - runnable, callable 인터페이스 사용 가능 79 | - runnable - 객체를 리턴하지 않음, exception 발생시키지 않음 80 | - callable - 값 리턴 가능, exception 발생시킬 수 있음 81 | - 객체 리턴이 필요하거나 exception 발생이 필요할 때 사용한다. 82 | 83 | ```java 84 | 85 | public class FutureEx { 86 | public static void main(String[] args) { 87 | ExecutorService es = Executors.newCachedThreadPool(); 88 | es.submit(() -> { 89 | Thread.sleep(2000); //interrupt 발생시 exception 던질 수 있도록 90 | log.info("Async"); 91 | return "Hello"; 92 | }); 93 | log.info("Exit"); 94 | } 95 | } 96 | ``` 97 | 98 | - #### FutureTask 99 | 100 | Future 자체를 Object로 만들어준다. 101 | 102 | ```java 103 | public class FutureEx { 104 | public static void main(String[] args) throws ExecutionException, InterruptedException { 105 | ExecutorService es = Executors.newCachedThreadPool(); 106 | FutureTask f = new FutureTask<>(()->{ 107 | Thread.sleep(2000); 108 | log.info("Async"); 109 | return "Hello"; 110 | }); 111 | es.execute(f); 112 | 113 | System.out.println(f.isDone()); //즉시 리턴(작업이 완료되었는지) 114 | Thread.sleep(2100); 115 | log.info("Exit"); 116 | System.out.println(f.isDone()); 117 | System.out.println(f.get()); 118 | } 119 | } 120 | 121 | ``` 122 | 123 | - FutureTask에 익명클래스로 done()메서드를 추가한 코드 124 | 125 | - 2초 후 Async 출력 126 | - Hello가 리턴되며 done()이 호출됨 127 | - get()호출로 Hello가 출력 128 | 129 | ```java 130 | public class FutureEx { 131 | public static void main(String[] args) throws ExecutionException, InterruptedException { 132 | ExecutorService es = Executors.newCachedThreadPool(); 133 | FutureTask f = new FutureTask<>(()->{ 134 | Thread.sleep(2000); 135 | log.info("Async"); 136 | return "Hello"; 137 | }) { //비동기 작업이 모두 완료되면 호출되는 hook같은 것. 138 | @Override 139 | protected void done() { 140 | try { 141 | System.out.println(get()); 142 | } catch (InterruptedException e) { 143 | e.printStackTrace(); 144 | } catch (ExecutionException e) { 145 | e.printStackTrace(); 146 | } 147 | } 148 | }; 149 | es.execute(f); 150 | es.shutdown(); //이 메서드를 쓰더라도 하던 작업이 중단되지는 않음 151 | } 152 | } 153 | 154 | ``` 155 | 156 | - Callback 157 | 158 | - Callback을 이용하여 비동기 실행 결과를 처리할 수 있는 코드 159 | - try/catch 작성이 빈번한 Future보다 더 우아한 코드라고 할 수 있다. 160 | - 더 나은 방법이 있지만, 기본기 중에서는 콜백 기법이 더 나음 161 | 162 | ```java 163 | 164 | public class FutureEx { 165 | interface SuccessCallback { 166 | void onSuccess(String result); 167 | } 168 | interface ExceptionalCallback{ 169 | void onError(Throwable t); 170 | } 171 | public static class CallbackFutureTask extends FutureTask { 172 | SuccessCallback sc; 173 | ExceptionalCallback ec; 174 | public CallbackFutureTask(Callable callable, SuccessCallback sc, ExceptionalCallback ec) { 175 | super(callable); 176 | this.sc = Objects.requireNonNull(sc); //Tip. Null이 들어오면 안될 때 사용하는 메서드 177 | this.ec = Objects.requireNonNull(ec); 178 | } 179 | 180 | @Override 181 | protected void done() { 182 | try { 183 | sc.onSuccess(get()); 184 | } catch (InterruptedException e) { 185 | Thread.currentThread().interrupt(); 186 | } catch (ExecutionException e) { 187 | ec.onError(e.getCause()); 188 | } 189 | } 190 | } 191 | 192 | public static void main(String[] args) throws ExecutionException, InterruptedException { 193 | ExecutorService es = Executors.newCachedThreadPool(); 194 | 195 | CallbackFutureTask f = new CallbackFutureTask(() -> { 196 | Thread.sleep(2000); 197 | if(1==1) throw new RuntimeException("Async ERROR!!!"); 198 | log.info("Async"); 199 | return "Hello"; 200 | }, 201 | s -> System.out.println(s), 202 | e-> System.out.println("Error: "+e.getMessage())); 203 | 204 | es.execute(f); 205 | es.shutdown(); //이 메서드를 쓰더라도 하던 작업이 중단되지는 않음 206 | } 207 | } 208 | ``` 209 | 210 | > ### Q) 동기, 비동기의 장단점 알려주세요. 211 | 212 | - 동기방식은 설계가 매우 간단하고 직관적이지만 결과가 주어질 때까지 아무것도 못하고 대기해야 하는 단점이 있고, 비동기방식은 동기보다 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있는 장점이 있다. 213 | 214 | > ### Q) node.js, spring을 동기,비동기, 블로킹, 논블로킹 관점에서 설명해주세요. 215 | 216 | - #### Spring vs Node.js 217 | 218 | - Spring: Multi-Thread, 동기방식, blocking 219 | 220 | - 노드 등장 이전 스프링은 멀티 쓰레드를 사용하여 다중요청을 동시에 처리하였음 221 | - 한개의 쓰레드가 하나의 요청을 담당하여 응답까지 책임지고 반환하고 요청이 들어오면 바로 \* 결과를 반환해주는 동기 방식을 사용하고 연산이 완료되는 동안 기다리는 블록킹 방식 222 | - 문제점 : 쓰레드가 응답을 기다리면서 블록킹하는 시간이 많아지면 효율적이지 않음 223 | 224 | - Node: single-Thread, 비동기 방식, non-blocking 225 | 226 | - 싱글 쓰레드를 사용하여 한개의 쓰레드에서 모든 요청을 처리하는 방식 227 | - 기존의 스프링과 달리 요청이 들어오면 바로 결과를 주는 것이 아니라 작업이 완료되는 대로 결과를 넘겨주는 비동기 방식 228 | - 한개의 쓰레드는 작업이 진행되는 동안 멈춰있는 것이 아니라 다른 작업을 수행할 수 있는 non-blocking 229 | - 문제점 : 갑자기 요청이 많아지고 복잡해지면 서버 반응이 느려진다. 230 | 231 | - #### Spring의 보완 (5 이후) 232 | 233 | - #### Spiring WebFlux 234 | 235 | - 스프링의 쓰레드 단점을 보완하고자 스프링 웹플럭스가 spring5부터 도입됨 236 | 237 | 노드의 장점을 가져와서 업그레이드함 238 | 기존의 멀티 쓰레드 방식을 유지하면서, 각각의 요청에 하나의 쓰레드가 대응되는 것이 아니라 싱글 쓰레드처럼 다수의 요청을 처리하게하게 되는 구조이다. 239 | 240 | - 스프링을 사용하면 좋은 경우 241 | 242 | - 복잡한 요구 사항이 많은 경우 스프링을 사용하는 것이 유리하다. ex) 실시간 게임, 영상처리 243 | node를 사용하면 좋은 경우 244 | - 간단한 요구사항이 많은 경우 노드를 사용하는 것이 유리하다. ex) 채팅, crud기반 서비스 245 | 246 | > ### Q) I/O작업이 잦은 경우 어떤 방식이 좋을까요? 247 | 248 | - 비동기 I/O의 장점은 I/O 작업이 완료되는 동안 호출자가 다른 작업을 수행하거나 더 많은 요청을 발급할 시간이 있기때문에 비동기 I/O가 더 효율적으로 처리할 수 있습니다. 249 | 250 | > ### Q) P2P 서비스 다운로드 받는 경우 4가지 경우를 어떻게 조합해서 사용할 수 있을지 상상해서 알려주세요. 251 | 252 | - 사용자는 주로 다운로드 받는 경우로 생각했을 때, 여러 파일을 효율적으로 다운받는 경우 비동기 + 논블로킹 방식으로 사용할 것 같습니다. 253 | 254 | > ### Q) 동기 + 논블로킹, 비동기 + 블로킹 방식이 잘사용되지 않는 이유는 무엇인가요? 255 | 256 | - #### 동기 + 논블로킹 257 | 258 | syn_async 259 | A 함수는 B 함수를 호출한다. 이 때 A 함수는 B 함수에게 제어권을 주지 않고, 자신의 코드를 계속 실행한다(논블로킹). 260 | 261 | 그런데 A 함수는 B 함수의 리턴값이 필요하기 때문에, 중간중간 B 함수에게 함수 실행을 완료했는지 물어본다(동기). 262 | 263 | 즉, 논블로킹인 동시에 동기인 것이다. 264 | 265 | - #### 비동기 + 블로킹 266 | 267 | syn_async 268 | 비동기 논블로킹은 이해하기 쉽다. A 함수는 B 함수를 호출한다. 269 | 270 | 이 때 제어권을 B 함수에 주지 않고, 자신이 계속 가지고 있는다(논블로킹). 따라서 B 함수를 호출한 이후에도 멈추지 않고 자신의 코드를 계속 실행한다. 271 | 272 | 그리고 B 함수를 호출할 때 콜백함수를 함께 준다. B 함수는 자신의 작업이 끝나면 A 함수가 준 콜백 함수를 실행한다(비동기). 273 | 274 | Async-blocking의 경우 sync-blocking과 성능의 차이가 또이또이하기 때문에 사용하는 경우는 거의 없다. 275 | 276 | > ### Q) Multiflexing I/O에 대해서 알려주세요. 277 | 278 | - #### I/O Multiplexing (멀티플렉싱, 다중화) 279 | 280 | - Asynchronous Blocking I/O 281 | 282 | 간단하게 말하면 '하나'를 '여러 개'처럼 동작하게 한다는 뜻이다. 이를 I/O 관점에서 해석하면 '한 process가 여러 파일(file)을 관리'하는 기법이라 볼 수 있다. 283 | 우리는 파일이 process가 kernel에 진입할 수 있도록 다리 역할을 해주는 interface 라는걸 알고 있다. 284 | 이 개념을 server-client 환경에 접목 시키면 하나의 server가 여러 socket 즉, 파일을 관리하여 여러 client를 수용할 수 있게 구성하는 것을 의미한다. 285 | 286 | 프로세스에서 특정 파일에 접근할 때는 File Descriptor(이하 FD)라는 추상적인 값을 사용하게 된다. 이 FD들을 어떻게 감시하냐는게 I/O Multiplexing의 주요 맹점이라 할 수 있다. 287 | 여기서 어떤 상태로 대기하냐에 따라 select, poll, epoll(linux), kqueue(bsd), iocp(windows) 등 다양한 기법들이 등장한다. 288 | -------------------------------------------------------------------------------- /Operating System/TLB, MMU.md: -------------------------------------------------------------------------------- 1 | # TLB, MMU 2 | 3 | ## 페이지 테이블의 TLB, MMU 에 대해 설명해주세요. 4 | 페이징 단위로 분할하여 적재를 하게 되면, **불연속적으로 데이터가 저장**되는데 , 이러한 데이터를 **CPU가 접근**할 수 있게 해주는 것이 **MMU** 입니다. 5 | 6 | TLB(Translation Lookaside Buffer)는 **주소 변환 속도를 높이기 위해** MMU(Memory Management Unit)에 저장된 최근에 액세스한 페이지 테이블 캐시입니다. 7 | 8 | ### Q) MMU가 생겨난 이유에 대해 설명해주세요. 9 | - 컴퓨터에서 제한된 메모리 문제를 해결하기 위해 만들어졌습니다. 초기 컴퓨터는 적은 양의 메모리를 가지고 있었으며 운영 체제가 수동으로 관리해야 했습니다. 프로그램의 크기와 복잡성이 증가함에 따라 운영 체제가 모든 메모리를 추적하는 것이 점점 어려워졌습니다. MMU는 **메모리 관리 과정을 자동화하고 CPU가 메모리를 더 효율적으로 관리할 수 있는 방법**을 제공하기 위해 설계되었습니다. 10 | 11 | 12 | ### Q) MMU에서 base register 를 통해 물리주소로 변환하는데 여기서 발생할 수 있는 문제에 대해 설명해주세요. 13 | > 💡 Hint: Memory Protection 14 | 15 | 프로세스를 불연속적으로 할당하면, 다른 프로세스가 메모리에 접근하는 경우가 생길 수 있습니다. 이를 예방하기 위해 limit 레지스터를 사용합니다. 16 | 프로세스의 접근 가능한 합법적인 메모리 영역(`x`)은 `base <= x < base+limit` 이 됩니다.따라서 이 영역 밖에서 접근을 요구하면 trap을 발생시킵니다. 17 | 안전성을 위해 base와 limit 레지스터는 사용자 모드에서는 직접 변경할 수 없도록 커널 모드에서만 수정 가능하도록 설계되어 있습니다. 18 | 19 | - **base 레지스터** : 메모리상의 프로세스 시작주소를 물리 주소로 저장 20 | - **limit 레지스터** : 프로세스의 사이즈를 저장 21 | 22 | ### Q) MMU, TLB, Page Table이 어디에 위치해있는 지 설명해주세요. 23 | ![image](https://user-images.githubusercontent.com/67494004/229360874-7a54c6e7-4b95-4ef6-b24f-36de1dbbb533.png) 24 | 25 | - MMU : CPU 내부 26 | - TLB : MMU 내부 27 | - Page Table : Main Memory 28 | - 💡 MMU : Page Table 의 위치정보를 관리하는 레지스터가 있음 29 | 30 | 31 | ### Q) MMU 와 TLB의 프로세스 사이 정보 공유 여부에 대해 설명해주세요. 32 | - TLB는 각 프로세스마다 개별적 메모리 공간에 지정되기 때문에, **프로세스 간에 정보를 공유하지 않습니다**. 가상메모리의 장점인 보호성에 기반하여, 서로 다른 프로세스가 같은 주소를 가르켜도 가상메모리에 의해 서로 영향을 주지 않습니다. 33 | 34 | 35 | ### Q) 가상메모리를 구현하기 위해 MMU가 사용하는 방식 36 | > Hint ! Page Table, Page Fault, Page Replacement 를 MMU 와 연관지어 설명 37 | - MMU는 **가상 메모리를 구현하기 위해 페이지 테이블을 사용**합니다. 38 | 페이지 테이블은 프로세스에서 사용하는 가상 주소와 물리 주소(해당 데이터가 저장되어있는 RAM)를 매핑합니다. 39 | 40 | **Page fault**는 페이지를 요구하였을 때 41 | 1. MMU가 페이지 테이블 내에 메모리에 있는 지, 해당 페이지의 valid bit 를 확인합니다.(0,1) 42 | 2. valid bit가 0 이라면, 페이지가 없는 경우이므로 Page fault 를 발생시킵니다. 43 | 3. 운영체제는 디스크에서 필요한 페이지를 검색하여 메모리에 로드합니다. 44 | 4. 페이지 테이블에 해당하는 메모리 valid bit를 1로 변경해줍니다. 45 | - valide bit는 dirty bit 등과 함께 사용되어 메모리의 페이지 상태를 추적 및 관리 46 | 47 | > ### Q) TLB를 사용할 때의 문제점 48 | > 💡 Hint ! Context Switching 49 | 50 | ![image](https://user-images.githubusercontent.com/67494004/229360941-a5749520-2a3f-452e-a68e-413a77c07f42.png) 51 | 52 | 53 | 컨텍스트 전환이 발생하면 운영 체제는 현재 프로세스의 상태를 저장하고 새 프로세스의 상태를 로드해야 합니다. 컨텍스트 전환 중에 TLB가 제대로 관리되지 않으면 새 프로세스에서 더 이상 유효하지 않은 이전 프로세스의 매핑이 포함될 수 있으며 이로 인해 잘못된 변환 및 시스템 충돌이 발생할 수 있습니다. 54 | 55 | 이 문제를 처리하기 위해 최신 운영 체제는 컨텍스트 전환 중에 "TLB flush"라는 기술을 사용합니다. TLB flush는 컨텍스트 스위치가 발생할 때 TLB의 모든 항목을 제거하는 프로세스로, CPU가 새 프로세스에 대한 올바른 매핑으로 TLB를 다시 로딩합니다. 56 | 57 | TLB flush는 CPU가 전체 TLB를 다시 로드해야 하기 때문에 시간이 걸릴 수 있습니다. 이 비용을 줄이기 위해 일부 최신 CPU에는 컨텍스트 전환 중에 이전 프로세스에 속한 페이지에 대해서만 TLB를 선택적으로 플러시할 수 있는 "PCID(프로세스 컨텍스트 식별자)"라는 기능이 포함되어 있습니다. 이렇게 하면 TLB를 다시 로드하는 데 필요한 시간이 줄어들고 전체 시스템 성능이 향상됩니다. 58 | 59 | 60 | ### Q) page Table 의 두가지 유형에 대해 설명해주세요. 61 | page Table 이 메모리에 함께 적재가 되면서 많은 크기를 차지한다는 단점이 있습니다. 만약 2^20(대략 100만)개의 페이지가 있다면, Page table 또한 각 페이지들이 물리 주소와 매핑될 수 있도록 100만개의 Page entry를 가지고 있어야 합니다. 62 | 63 | 페이지 테이블의 크기가 커지면서 전체 테이블을 메모리에 저장하는 것이 점점 어려워졌습니다. 이로 인해 페이지 테이블을 여러 수준으로 나누어 크기를 줄이고 메모리 효율성을 향상시키는 계층적 페이지 테이블(Hierarchical Page Table)이 개발되었습니다. 64 | 65 | - 계층적 페이지 테이블(Hierarchical page table) 66 | - 해시 페이지 테이블 (Hashed page table) 67 | - 역페이지 테이블 (Inverted page table) 68 | 69 | image 70 | 71 | 72 | 계층적 페이지 테이블 에 대해 더 자세하게 설명해보겠습니다. 73 | 계층적 페이지는 Page table의 사이즈를 줄이기 위해 고안된 방법으로, 기존에 프로세스 하나당 하나의 Page table을 사용하던 것을 여러 개로 나누어 사용하는 방식을 의미합니다. 74 | 계층을 나눈 횟수만큼 level이 증가하여 두 번 나누었다면 2-level page table, 세 번 나누었다면 3-level page table 이라는 이름을 붙입니다. 75 | 76 | - Level 1인 outer page table에서는 해당 page number가 valid한지 invalid한지 판단 77 | - invalid : level 2에 page table이 존재하지 않는 것이기 떄문에 memory 절약을 할 수 있게 되는 것 78 | - valid : outer page table이 가리키고 있는 level 2의 page table에서 page number를 찾아 frame number를 통해 physical address를 계산 79 | 80 | - P1은 outer page table의 entry 개수(인덱스)이고 P1을 통해 Level 2의 page table의 시작주소를 알 수 있다. 81 | - P2값을 통해 frame number를 알 수 있다. 만약 64bit를 사용한다면 P1은 42, P2는 10, offset은 12bit를 가진다. 만약 계층 구조의 page table을 사용하지 않는다면 page number는 52bit를 사용하게 되어 size가 더욱 커질 것이다. 82 | - level을 늘려서 page table의 사이즈를 더 줄일 수 있다. 실제 Linux에서는 Level 3의 계층 구조를 사용하고 있다. 위 그림에서 하나의 page table을 추가하여 P1->P2->P3을 거쳐 frame number를 찾는 구조로 되어있다. 83 | 84 | 계층을 나누면 페이지 테이블을 Paging하기 때문에 기존에 메모리를 효율적으로 사용할 수 있습니다. 85 | 또한 나눌수록 페이지 테이블의 크기는 줄어들지만, 각 페이지 테이블을 참조하기 위해 level이 커질수록 메모리를 자주 참조해야 한다는 단점이 발생합니다. 86 | 87 | 88 | 89 | ### Q) TLB 에 원하는 주소가 없을 때의 2가지 경우, Main Memory와 Page 용어를 사용해서 말씀해주세요. 90 | miss가 일어났을 때 TLB에 원하는 주소가 없는 경우는 2가지로 나뉠 수 있습니다. 91 | 1. TLB는 없지만 mainMemory 에 있는 경우, mainMemory에서 가져와 -> TLB 92 | 2. mainMemory에도 없다면 , page Fault -> 관련 처리 루틴 93 | 을 통해 TLB miss 를 처리합니다. 94 | 95 | ### MultiLevel pageTable 96 | == Hierarchical Page Table 97 | 98 | 99 | #### 이미지 및 내용 참고 100 | https://velog.io/@mardi2020/페이지-교체-알고리즘 101 | TLB: https://icksw.tistory.com/149 102 | 계층 테이블 : https://itstory1592.tistory.com/103 103 | -------------------------------------------------------------------------------- /Operating System/Virtual Memory.md: -------------------------------------------------------------------------------- 1 | ### 메모리의 연속할당 방식 세 가지를 설명 & 가상메모리 2 | - 고정분할방식 3 | - 물리메모리를 특정개수로 분할해서 적재하는방식. 4 | - 내부단편화, 외부단편화 생길수있음 5 | 6 | - 가변분할방식 7 | - 메모리에 적재되는 프로그램에 따라 크기,개수가 동적으로 변하는방식. 8 | - 외부단편화 문제 생길수있음 9 | 10 | 빈공간 할당을 위한 전략으론 크게 아래의 3가지 방법이 있다. 11 | 12 | 최적적합(best) 13 | => 빈 공간리스트를 검색해 요청한 메모리 크기와 같거나 더 큰 빈 메모리 덩어리를 찾는다. 그후 후보그룹중 가장 작은 크기의 단위를 반환한다. 빈공간 리스트를 한번만 순회하면 반환할 정확한 블럭을 찾을수있다. **전체를 검색해야하기때문에 성능저하가 있을수있다**. 14 | 15 | 최악 적합(worst) 16 | => 가장 큰 빈 덩어리를 찾아 요청 크기만큼만 반환하고 남은부분은 빈 공간 리스트에 계속 유지한다. 최적적합에서 가장작은 덩어리를 남기려는 대신 최악적합에서는 가장 큰 덩어리를 남기려고 시도한다. **빈 공간 전체를 검색해야하기때문에 성능 저하가 있을수있다**. 그리고 **단편화**가 발생할수도있다. 17 | => 운영체제가 제공하는 공간이 넉넉한경우에만 사용할수있을것이다. 18 | 19 | 최초 적합(first) 20 | => 요청보다 큰 첫번쨰 블럭을 찾아 요청만큼 반환한다. **블럭 전체를 안뒤져도 되니까 속도가 빠르다는 장점**이있지만 **리스트의 시작부분에 크기가 작은 객체가 많이 생길수있다**는 단점이있다. (주소 기반 정렬을 사용해 리스트를 주소로 정렬해서 단편화를 감소시키는 방법이있긴하다) 21 | 22 | - 가상메모리 23 | - 하드드라이브의 일부를 물리적 메모리로 확장해서 사용하여 컴퓨터가 실제 메모리보다 큰 프로그램을 실행할수있도록 해주는것 24 | 25 | > #### Q) 메모리 공간 관점으로 위의 전략3가지에 대해 설명해주세요 26 | - 최초적합방식은 적합한 메모리블록을 발견즉시 반환해주기때문에 사용하지않는 메모리 공간들로 인해 단편화 문제가 생길수있습니다. 27 | - 최악적합방식은 충분히 큰 메모리블록을 할당하기때문에 메모리 공간 전체를 사용할필요가 없어도 큰 메모리 공간할당으로 인해 내부단편화 문제가 생길수있습니다. 28 | - 최적적합방식은 충분한 검색후 메모리를 할당하기때문에 위의 3가지 방식중 단편화의 비용이 가장 적다고 볼수있습니다. 29 | 30 | 31 | #### Q) 가상메모리가 가능한 이유에 대해 설명해주세요. 32 | - 프로그램이 실행 프로그램의 메모리상태를 갖고있는 주소공간을 통해 가상메모리와 실제메모리의 매핑을 추적하기때문에 가능하다. 33 | - MMU가 가상메모리, 물리메모리를 매핑하는 테이블을 사용해서 매핑된정보를 확인할수있기때문에 가능하다. 34 | 35 | > #### Q) 가상메모리로 인해 얻을수있는 이점에 대해 설명해주세요 36 | - 프로세스 전환시 프로세스를 메모리에 그대로 유지하면서 운영체제가 시분할 시스템을 효율적으로 구현할수있게되었다. (context switching 의 오버헤드 감소) 37 | - 메모리 의존성(하드웨어 스펙 등)에서 자유로워졌다. 38 | - 메모리 보호, 관리부분에서 용이하다. 39 | - 특정 프로세스가 죽어버리더라도 해당 프로세스의 실제영역을 운영체제가 알고있기때문에 자원을 신속히 회수할수있으며, 자원과 메모리공간의 낭비가 없다. 40 | 41 | #### Q) 내부단편화, 외부단편화에대해 설명해주세요 42 | - 내부단편화 : 필요한 크기보다 더큰 메모리덩어리를 할당하면 할당 덩어리의 내부에서 낭비가 일어나게되는데 이를 내부단편화라고한다. 43 | - 외부단편화 : 64KB 물리메모리가 있다고 가정할때, 연속되지않은 8KB의 공간이 3개가있을때 20KB크기를 가진 프로세스를 할당하려는경우 요청을 충족할수없는경우를 말한다. 44 | 45 | #### Q) 단편화의 문제를 해결할수있는 방법에대해 설명해주세요 46 | - 압축방식 : 외부단편화 문제를 해결하기위한 수단으로 현재 프로세스를 중단하고 그들의 데이터를 하나의 연속된 공간에 복사하고 세그멘트 레지스터가 새로운 물리 메모리위치를 가리키게 하는 방식으로압축할수있다.세그멘트 복사자체가 비용이 크다는 단점이 있다. 47 | - 통합 : 단편화로 인해 분산된 메모리공간들을 인접해 있는 것끼리 통합시켜 큰 메모리 공간으로 합치는 기법이다. 압축은 복사후 재배치 과정의 오버헤드가있지만 통합은 인접한 공간들끼리 통합된다는 차이가 있다. 48 | 49 | 50 | #### Q) 자바의 GC가 무엇인가요 51 | - 자바에서 동적으로 메모리가 할당되는 Heap영역에서 더이상 사용되지않는 메모리를 회수해가는것 52 | 53 | 54 | > #### Q) 가상메모리는 대략 어느정도의크기를 가지고 있나요? 55 | - 이론적으로는 무한대지만 물리 메모리의 크기, CPU비트수에 의해 결정된다. 56 | - 32bit의 운영체제로 가정할때 2^32 = 4GB크기를 가지고있다. 57 | 58 | 59 | > #### Q) 프레임 할당은 어떻게 이루어지고, 프레임 할당하는방식중 한가지만 설명해주세요 60 | - 프로세스마다 사용하는 페이지가 다르기때문에 크기는 그때그때 달라질수있다. 이를고려해 프레임을 할당하는 방식인 **동적할당**이 존재한다. 61 | - 동적할당 방식중 Working Set Model 방식이있는데 이는 시간을 측정해서 주로 참조하는 페이지를 계산하고 이값을통해 프레임을 할당하는방식이다. 62 | - PFF는 페이지결함의 비율을 측정하여 프레임을 할당하는 방식이다. 프로세스의 페이지 부재율을 주기적으로 조사하고 이 값에 근거해서 각 프로세스에 할당할 메모리 양을 동적으로 조절하는 방식 63 | 64 | > #### Q) 자바에서도 가상메모리를 사용할까? 65 | - GC를통해 자동메모리관리를 사용한다. 66 | - 자바의 가상메모리는 JVM수준에서 관리되는반면 C의 가상메모리는 운영체제에서 직접관리되는다는 차이점이 있다. 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📚 CS-JAVA-STUDY 😎 2 | 3 | > 👋 CS/JAVA 스터디에 오신 걸 환영합니다!

4 | 저희 스터디는 23/3/13 ~ 23/5/24 약 2달간 모의면접을 통해

5 | 면접 능력 향상, 탄탄한 컴퓨터 지식에 초점을 두고

6 | 운영체제(3주) → 자료구조, 알고리즘(2주) → 자바(2주) → 네트워크(2주) → DB(2주)동안 공부한 내용을 정리했습니다. 7 |

8 | ### 운영체제 9 | [CPU 스케쥴링](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/CPU%20Sheduling.md) 10 | [캐시 메모리 & 메모리 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Cache%20Memory%20%26%20Memory%20Layered.md) 11 | [컨텍스트 스위칭 & PCB](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Context%20Switching%20%26%20PCB.md) 12 | [임계 구역](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Critical%20Section.md) 13 | [데드락](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Deadlock.md) 14 | [파일 시스템](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/File%20System.md) 15 | [인터럽트](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Interrupt.md) 16 | [페이지 교체 알고리즘](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Page%20Replacement%20Algorithm.md) 17 | [페이징 & 세그멘테이션](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Paging%20%26%20Segmentation.md) 18 | [프로세스와 스레드](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Process.md) 19 | [동기 & 비동기 & 블럭 & 논블럭](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Synchronous%20%26%20Asynchronous%20%26%20blocking%20%26%20nonblocking.md) 20 | [TLB, MMU](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/TLB%2C%20MMU.md) 21 | [가상 메모리](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Operating%20System/Virtual%20Memory.md) 22 | 23 | --- 24 | ### 자료구조, 알고리즘 25 | [배열 & 리스트](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Data%20Structure/Array.md) 26 | [그래프](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Data%20Structure/Graph.md) 27 | [해시](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Data%20Structure/Hash.md) 28 | [스택 & 큐](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Data%20Structure/Stack%2C%20Queue.md) 29 | [트리 & 힙](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Data%20Structure/Tree%20%26%20Heap.md) 30 | 31 | [완전 탐색 & 재귀](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Algorithm/%EC%99%84%EC%A0%84%ED%83%90%EC%83%89%2C%20%EC%9E%AC%EA%B7%80.md) 32 | [DP & Greedy](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Algorithm/DP%2C%20%EB%B6%84%ED%95%A0%20%EC%A0%95%EB%B3%B5%2C%20%EA%B7%B8%EB%A6%AC%EB%94%94.md) 33 | [분할 정복 법](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Algorithm/Divide%20%26%20Conquer.md) 34 | [정렬](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Algorithm/Sorting.md) 35 | [그래프](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Algorithm/Graph.md) 36 | 37 | --- 38 | ### 자바 39 | [JVM](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/JVM.md) 40 | [GC](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/GC.md) 41 | [JDK 8](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/JDK8.MD) 42 | [객체지향언어](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/OOP.md) 43 | [제어자](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/Modifier.md) 44 | [접근 제어자](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/AccessModifier.md) 45 | [Wrapper class](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/Wrapper.md) 46 | [제너릭](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/Generic.md) 47 | [Collection Framework](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/CollectionFramework.md) 48 | [Error & Exception](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/Error%20%26%20Exception.md) 49 | [Synchronization](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Java/Synchronization.md) 50 | 51 | --- 52 | ### 네트워크 53 | [HTTP, HTTPS](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/HTTP%2CHTTPS.md) 54 | [웹 점속 과정](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/%EC%9B%B9%20%EC%A0%91%EC%86%8D%20%EA%B3%BC%EC%A0%95.md) 55 | [웹서버, 웹 애플리케이션 서버](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/%EC%9B%B9%EC%84%9C%EB%B2%84%2C%20WAS.md) 56 | [네트워크 접근 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/Network%20Access%20Layer%20(Physical%20%26%20Data).md) 57 | [인터넷 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/Internet%20Layer%20(Network%20Layer).md) 58 | [전송 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/TransportLayer.md) 59 | [TCP, UDP](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/TCP%2C%20UDP.md) 60 | [세션 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/SessionLayer.md) 61 | [표현 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/PresentationLayer.md) 62 | [응용 계층](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/ApplicationLayer.md) 63 | [REST API](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/REST%20API.md) 64 | [쿠키, 세션, OAuth, JWT](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Network/Cookie%2C%20Session%2C%20OAuth%2C%20JWT.md) 65 | 66 | --- 67 | ### DB 68 | [Query](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Database/sql%20query.md) 69 | [데이터베이스 종류와 특징](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Database/Database%2C%20key.md) 70 | [정규화](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Database/Normalization.md) 71 | [인덱스](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Database/Index.md) 72 | [클러스터링 & 복제](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Database/Clustering%2C%20Replication.md) 73 | [파티셔닝 & 샤딩](https://github.com/bombo-dev/CS-JAVA-Study/blob/main/Database/Partitioning%20%26%20Sharding.md) 74 | 75 | --- 76 | --------------------------------------------------------------------------------