├── Algorithm └── README.md ├── Database └── README.md ├── Datastructure └── README.md ├── DesignPattern └── README.md ├── Etc └── README.md ├── Java └── README.md ├── LICENSE ├── LiveCoding └── README.md ├── Network └── README.md ├── OOP └── README.md ├── OS └── README.md ├── README.md ├── Spring └── README.md ├── SystemDesign └── README.md └── Web └── README.md /Algorithm/README.md: -------------------------------------------------------------------------------- 1 | # Algorithm 2 | 3 |
4 | 5 |
6 | 시간 복잡도와 공간 복잡도 7 |
8 | 9 | #### 표기법 10 | 11 | * 주로 `빅오 표기법`으로 표현 12 | 13 | #### 시간 복잡도 14 | * 알고리즘의 `수행 시간`을 분석하는 방법 15 | 16 | #### 공간 복잡도 17 | * 알고리즘 수행에 필요한 `메모리 양`을 분석하는 방법 18 | 19 |
20 |
21 | 22 | 23 |
24 | 정렬 알고리즘에서의 Stable 25 |
26 | 27 | * 정렬 기준으로 봤을 때, `값이 동일한 Element가 있어도 정렬 전의 순서와 정렬 후의 순서가 동일함을 보장`하는 것 28 | 29 |
30 |
31 | 32 | 33 |
34 | 정렬 알고리즘의 가짓수가 많은 이유 35 |
36 | 37 | * `공간 복잡도`에 따라 사용해야할 알고리즘이 다름 -> Merge Sort의 공간 복잡도는 Selection Sort와 Insertion Sort에 비해 큼 38 | * `안정 정렬`이냐 `불안정 정렬`이냐에 따라 사용해야 할 때가 다름 39 | 40 |
41 |
42 | 43 | 44 |
45 | Selection Sort 46 |
47 | 48 | * 최선, 평균, 최악: O(n^2) 49 | * `불안정 정렬 알고리즘` 50 | * 가장 작은 값을 가지는 데이터를 찾아서 가장 작은 값을 앞에서부터 채워 나가면서 정렬하는 방식으로 동작 51 | * 1번의 순환마다 맨 앞의 값이 고정 52 | * 정렬을 위해 비교하는 횟수는 많으나, 교환 횟수는 적음 -> 역순으로 정렬되어 있는 것과 같이 많은 교환이 필요한 상태에서 효율적으로 사용 가능 53 | 54 |
55 | 코드 56 |
57 | 58 | ```java 59 | public static void selectionSort() { 60 | for (int i = 0; i < array.length-1; ++i) { 61 | for (int j = i+1; j < array.length; ++j) { 62 | if (array[i] > array[j]) { 63 | int tmp = array[i]; 64 | array[i] = array[j]; 65 | array[j] = tmp; 66 | } 67 | } 68 | } 69 | } 70 | ``` 71 | 72 |
73 |
74 | 75 |
76 |
77 | 78 | 79 |
80 | Bubble Sort 81 |
82 | 83 | * 최선, 평균, 최악: O(n^2) 84 | * `안정 정렬 알고리즘` 85 | * 처음부터 끝까지 인접한 두 데이터를 비교하면서 큰 값을 맨 뒤로 보내는 방식으로 동작 86 | * 1번의 순환마다 맨 뒤의 값이 고정 87 | 88 |
89 | 코드 90 |
91 | 92 | ```java 93 | public static void bubbleSort() { 94 | for (int i = array.length - 1; i > 0; --i) { 95 | for (int j = 0; j < i; ++j) { 96 | if(array[j] > array[j+1]) { 97 | int tmp = array[j]; 98 | array[j] = array[j+1]; 99 | array[j+1] = tmp; 100 | } 101 | } 102 | } 103 | } 104 | ``` 105 | 106 |
107 |
108 | 109 |
110 |
111 | 112 | 113 |
114 | Merge Sort 115 |
116 | 117 | * 최선, 평균, 최악 시간 복잡도: O(NlogN) 118 | * 이유: 배열을 반씩 나눠서 1개 원소로 나누는 것은 `logN`, 합치는 것도 `logN`번 수행, 합치면서 `N`개 원소들을 읽으면서 비교 119 | * `안정 정렬 알고리즘`, `분할 정복` 120 | * 배열을 반으로 쪼개 가면서 하나의 원소를 가진 배열로 만든 이후에 쪼개진 각 배열을 정렬하면서 병합하여 최종 정렬된 배열을 완성 121 | 122 |
123 | 코드 124 |
125 | 126 | ```java 127 | static int[] array = new int[N]; // 원본 배열 128 | static int[] sorted = new int[N]; // 합치는 과정에서 정렬된 원소를 저장하는 임시 배열 129 | 130 | mergeSort(0, array.length-1); 131 | 132 | public static void mergeSort(int left, int right) { 133 | if (left < right) { 134 | int mid = (left+right) / 2; 135 | mergeSort(left, mid); 136 | mergeSort(mid+1, right); 137 | merge(left, mid, right); 138 | } 139 | } 140 | 141 | public static void merge(int left, int mid, int right) { 142 | int l = left, m = mid+1, k = left; 143 | while (l <= mid && m <= right) { 144 | if (array[l] <= array[m]) sorted[k++] = array[l++]; 145 | else sorted[k++] = array[m++]; 146 | } 147 | 148 | if (l > mid) { 149 | for (int i = m; i <= right; ++i) sorted[k++] = array[i]; 150 | } else { 151 | for (int i = l; i <= mid; ++i) sorted[k++] = array[i]; 152 | } 153 | 154 | for (int i = left; i <= right; ++i) array[i] = sorted[i]; 155 | } 156 | ``` 157 | 158 |
159 |
160 | 161 |
162 |
163 | 164 | 165 |
166 | Quick Sort 167 |
168 | 169 | * 최선, 평균: O(NlogN) / 최악: O(N^2) 170 | * `불안정 정렬 알고리즘`, `분할 정복 알고리즘` 171 | * `파티셔닝` 아이디어를 재귀적으로 활용 172 | * `파티셔닝`이란 pivot 원소를 기준으로 왼쪽은 pivot보다 작은 원소들로 모으고 오른쪽은 pivot보다 큰 원소로 모으는 것을 의미하는데 pivot을 기준으로 파티셔닝이 완료되면 pivot을 고정하고 같은 과정을 `재귀호출` 하여 반복하며 정렬 173 | * 과정 (오름차순 정렬) 174 | - 가장 기본적인 퀵 정렬은 첫 번째 데이터를 pivot 으로 설정 175 | - pivot을 제외하고 왼쪽에서부터 pivot 보다 큰 데이터를 선택, 오른쪽에서부터 pivot 보다 작은 데이터를 선택해 교환 176 | - 두개의 위치가 겹치거나 엇갈린 경우, `pivot`과 두 데이터 중 `작은 데이터`의 위치를 서로 변경 (**작은 데이터가 pivot이 된다**) 177 | - 이제 pivot을 기준으로 왼쪽은 모두 pivot보다 작고, 오른쪽은 모두 pivot보다 크다. (파티셔닝) 178 | - 재귀적으로, 왼쪽과 오른쪽 모두 위의 방법을 순서대로 진행 179 | * Quick Sort가 통상적으로 가장 빠른 정렬을 지원하지만 `Worst Case에서 O(n^2)`이므로 Tim Sort나 Heap Sort를 사용하기도 함 180 | * 최악: 정렬된 배열에서 피봇을 최대/최소 값으로 선택 181 | 182 |
183 | 코드 184 |
185 | 186 | ```java 187 | quickSort(0, array.length-1); 188 | 189 | private static void quickSort(int low, int high) { 190 | if (low >= high) return; 191 | int mid = partition(low, high); 192 | quickSort(low, mid - 1); 193 | quickSort(mid, high); 194 | 195 | private static int partition(int low, int high) { 196 | int pivot = array[(low + high) / 2]; 197 | while (low <= high) { 198 | while (array[low] < pivot) low++; 199 | while (array[high] > pivot) high--; 200 | if (low <= high) { 201 | int tmp = array[low]; 202 | array[low] = array[high]; 203 | array[high] = tmp; 204 | low++; 205 | high--; 206 | } 207 | } 208 | return low; 209 | } 210 | ``` 211 | 212 |
213 |
214 | 215 |
216 |
217 | 218 | 219 |
220 | Insertion Sort 221 |
222 | 223 | * 최선: O(n) / 평균, 최악: O(n^2) 224 | * 2번째 원소부터 시작하여 그 앞의 원소들과 비교하여 삽입할 위치를 지정한 후, 원소를 뒤로 옮기고 지정된 자리에 자료를 삽입하여 정렬 225 | 226 |
227 | 코드 228 |
229 | 230 | ```java 231 | private static void insertionSort() { 232 | int j; 233 | for (int i = 1; i < array.length; ++i) { 234 | int key = array[i]; 235 | for (j=i-1; j>=0 && array[j]> key; --j) { 236 | array[j+1] = array[j]; 237 | } 238 | array[j+1] = key; 239 | } 240 | } 241 | ``` 242 | 243 |
244 |
245 | 246 |
247 |
248 | 249 | 250 |
251 | Heap Sort 252 |
253 | 254 | * 최선, 평균, 최악: O(NlogN) 255 | * `불안정 정렬 알고리즘` 256 | * 완전 이진 트리를 기본으로 하는 힙에 데이터를 삽입하고 꺼내서 힙을 통해 정렬 257 | 258 |
259 |
260 | 261 | 262 |
263 | Counting Sort 264 |
265 | 266 | * 데이터의 개수를 Count 해서 정렬하는 것 267 | * 데이터의 갯수가 N, 데이터(양수) 중 최댓값이 K일 때 최악의 경우에도 수행 시간 `O(N+K)` 보장 268 | * 속도가 빠르지만, 수의 범위가 극단적으로 클 경우에는 메모리 낭비가 될 수 있음 269 | * `데이터의 범위가 제한되어 0 또는 양수 형태로 표현할 수 있을 때` 사용 270 | 271 |
272 |
273 | 274 | 275 |
276 | 이분 탐색 277 |
278 | 279 | * `이미 정렬되어 있는 자료구조`에서 특정 값을 탐색할 때 탐색 범위를 반으로 쪼개서 값을 찾아가는 알고리즘 280 | * `O(logN)`으로 순차 탐색보다 빠르지만 탐색을 위해 정렬을 하면 순차 탐색보다 더 높은 시간복잡도를 갖게 됨 281 | 282 |
283 |
284 | 285 | 286 |
287 | Fibonacci 공식을 재귀적인 방법과 동적 계획법을 이용했을 때 각각의 차이 288 |
289 | 290 | * 재귀적인 방법인 경우 재귀 호출 시에 중복되는 연산이 계속 수행 291 | * 동적 계획법의 경우 이전 값을 `메모리제이션`하기 때문에 중복 연산이 수행되지 않음 292 | 293 |
294 |
295 | 296 | 297 |
298 | DFS와 BFS 299 |
300 | 301 | * DFS는 `스택이나 재귀호출`로 구현할 수 있는 탐색 방법으로 한 정점으로부터 연결되어 있는 한 정점으로만 나아가는 방식 302 | * BFS는 `큐`를 통해서 구현할 수 있는 탐색 방법으로 한 정점으로부터 연결되어 있는 모든 정점을 나아가며 탐색하는 방식으로 BFS로 구한 경로는` 최단 경로`라는 장점이 존재 303 | 304 |
305 |
306 | 307 | 308 |
309 | 재귀호출을 이용할 때의 문제점 310 |
311 | 312 | * 스택의 범위를 초과할 수 있음 313 | 314 |
315 |
316 | 317 | 318 |
319 | 트리 순회 방법 320 |
321 | 322 | * 전위 순회(Pre-order): root 방문 -> 왼쪽 서브트리 방문 -> 오른쪽 서브트리 방문 323 | * 중위 순회(In-order): 왼쪽 서브트리 방문 -> root 방문 -> 오른쪽 서브트리 방문 324 | * 후위 순회(Post-order): 왼쪽 서브트리 방문 -> 오른쪽 서브트리 방문 -> root 방문 325 | 326 |
327 |
328 | -------------------------------------------------------------------------------- /Database/README.md: -------------------------------------------------------------------------------- 1 | # Database 2 | 3 |
4 | 5 |
6 | DBMS 7 |
8 | 9 | * 데이터베이스 관리 시스템(DataBase Management System) 10 | * 데이터베이스의 데이터에 접근하여 사용할 수 있도록 해주는 SW 11 | * 정의, 조작, 제어 기능 수행 12 | 13 | |기능|설명| 14 | |:--:|--| 15 | |정의|DB 구조 정의(테이블, 속성)| 16 | |조작|DB 연산 처리(수정, 삭제, 검색)| 17 | |제어|데이터 무결성 및 일관성 유지, 접근 권한 부여, 동시성 제어| 18 | 19 |
20 |
21 | 22 | 23 |
24 | DB를 사용하는 이유 25 |
26 | 27 | * `파일 시스템의 문제를 해결`하기 위해 사용 28 | * 확장성이 좋음: 파일 시스템은 OS 종속적 29 | * 중복 최소화, 보안성, 계속적 변화에 대한 적응: 파일 시스템은 데이터 중복, 비일관성, 검색 등의 문제 존재 30 | * DB는 `원자적 갱신`, `동시성 제어`, `데이터 보호`, `백업 및 회복` 등의 여러 데이터 관리 기능을 통해 데이터를 편하게 관리할 수 있음 31 | * 일반적으로 서버는 Scale-Out 구조로 설계되고 DB는 Scale-Up 구조로 설계되기 때문에 DB의 부담을 줄이고 애플리케이션에서 최대한 많은 처리를 하는 것이 권장 32 | 33 |
34 |
35 | 36 | 37 |
38 | 관계형 데이터베이스(SQL)와 비관계형 데이터베이스(NoSQL)의 차이 39 |
40 | 41 | #### 관계형 데이터베이스 42 | * 엄격한 스키마 아래 행과 열로 구성된 `테이블`들의 관계로 데이터 저장 43 | * SQL을 사용해서 `속성(열)에 맞는 자료형`으로 데이터를 삽입 44 | * ACID 45 | * 데이터 무결성 보장, 데이터를 중복 없이 저장 46 | * 기존의 스키마 수정 어려움, 빅데이터 처리에 비효율적 47 | * 데이터가 자주 변경되거나 명확한 스키마가 있는 경우 사용 48 | * `Oracle`, `MySQL` 49 | 50 | #### 비관계형 데이터베이스 51 | * 스키마가 없거나 느슨한 스키마로 데이터 저장 (`key-value`, `Document` 등) 52 | * 데이터 질의 API 다양함 53 | * Eventual Consistency 54 | * 유연하고 확장성 좋음 55 | * 데이터를 자주 변경하지 않고 정확한 데이터 구조를 알 수 없는 경우 사용 56 | * 키-값: `Redis`, 문서형(JSON, XML): `MongoDB` 57 | 58 |
59 |
60 | 61 | 62 |
63 | NoSQL(Not Only SQL) 64 |
65 | 66 | * 관계형 데이터베이스가 아닌 다른 형태 67 | 로 데이터를 저장하는 기술 68 | * 특징 69 | * 반정형(명확한 스키마 없음, 일정 수준의 자유도 허용, NoSQL/JSON 형태의 데이터)/비정형(스키마 없음, 비디오/오디오 등의 멀티미디어 데이터) 데이터에 적합 70 | * ACID 대신 Eventual Consistency: Consistency를 조금 타협하고 꼭 실제 최신은 아닐 수 있지만 `업데이트가 되기 전까지는` 가지고 있는 최신의 데이터를 반환함을 의미 -> 분산형의 특성상 일관성 유지가 어려움 71 | * 대용량/분산형 데이터 저장에 유리 72 | * 특정 도메인의 문제 해결에 좋음: Key-value, Graph 등 자료 형태가 다양해 특정 분야에서 고성능(소셜 네트워크: 인간 관계는 그래프) 73 | * 데이터를 질의하는 API가 다양 74 | * 분산형 컴퓨터에 최적화, 확장성 좋음: 머신의 수를 늘리는 `수평적 확장` 75 | * NoSQL은 SQL보다 제품 지원이 어려움 76 | * 인력 운영 비용이 더 비쌈: 표준화 부족, 질의 언어 다양 77 | * 종류 78 | * Column-based: 열 별로 연속적으로 저장, 기존 SQL은 테이블에 행 단위로 순차적으로 저장 -> 레코드의 특정 부분만 수정할 때, 필요한 열의 데이터만 로드하면 되서 IO 작업 감소, 한 열에 들어가는 데이터 형식에 일관성이 있어 DB 내의 한 블록은 동일한 유형의 데이터를 보유 -> 데이터의 유형에 맞는 압축 인코딩 가능, 디스크 공간 절약 및 성능 향상 가능 79 | * Document-oriented: JSON 객체로 문서(레코드)를 구성, 다양항 구조로 테이블 구성 가능, `MongoDB` 80 | * Key-Value: 연관 배열을 데이터 모델로 이용, Key는 한 Collection에 한 번만 등장 가능 81 | * Graph 82 | 83 |
84 |
85 | 86 | 87 |
88 | 테이블 89 |
90 | 91 | #### 테이블 92 | * 행과 열로 이루어진 데이터의 집합 93 | 94 | #### 행 95 | * 테이블을 구성하는 데이터 셋으로 `튜플`이나 `레코드`라고 불림 96 | * 한 객체에 대한 정보를 가짐 97 | 98 | #### 열 99 | * 테이블을 구성하는 데이터 셋으로 `속성`이라고 불림 100 | 101 | #### 도메인 102 | * 데이터베이스 필드에 채워질 수 있는 `값들의 집합` 103 | 104 |
105 |
106 | 107 | 108 |
109 | 110 |
111 | 112 | * 하나 이상의 테이블에서 유도된, 메모리에 물리적으로 존재하지 않는 `가상 테이블` 113 | * 특정 사용자로부터 특정 속성을 `숨기는` 기능으로 뷰를 정의하여 그 뷰를 테이블처럼 사용 114 | * 인덱스를 가질 수 없고, 뷰의 정의를 변경할 수 없음 115 | * 테이블의 기본키를 포함하여 정의 시, 삽입/삭제/갱신 가능 116 | 117 |
118 |
119 | 120 | 121 |
122 | 조인 123 |
124 | 125 | * 두 개 이상의 테이블을 `연결하여 데이터를 검색`하는 방법 126 | * 적어도 하나의 칼럼을 서로 공유하고 있어야 함 127 | 128 |
129 |
130 | 131 | 132 |
133 | 스키마와 테이블의 차이 134 |
135 | 136 | #### 스키마 137 | * 데이터베이스의 데이터 구조에 대한 공식적인 설명 -> 테이블, 열, 데이터 유형, 인덱스 등의 정의를 포함 138 | 139 | #### 테이블 140 | * `행과 열로 구성된 데이터 집합` 141 | 142 |
143 |
144 | 145 | 146 |
147 | 148 |
149 | 150 | 151 | 152 | #### 정의 153 | * 검색, 정렬 시 튜플을 구분하는 기준이 되는 속성 (Attribute) 154 | * 무조건 레지스터에 한번에 들어갈 수 있는 INT, LONG, DATETIME 속성을 사용하는 것이 권장 155 | * 용어 156 | * 유일성: 키로 튜플을 유일하게 식별할 수 있음 157 | * 최소성: 튜플을 구분하는데 꼭 필요한 속성들로만 구성 158 | 159 | #### 슈퍼 키 160 | * 유일성을 만족, 최소성은 만족하지 않는 속성들의 집합 161 | 162 | #### 후보 키 163 | * `유일성`과 `최소성`을 만족하는 속성들의 집합 164 | * 기본 키로 사용할 수 있는 속성들 165 | * 모든 테이블은 하나 이상의 후보 키를 가짐 166 | 167 | #### 기본 키 168 | * 후보 키 중에서 선택한 Main Key (주 키) 169 | * `유일성`과 `최소성` 만족 170 | * 중복 값과 NULL 값 불가 (`개체 무결성`) 171 | * 데이터 저장 시에 기본 키(PK)가 유사한 레코드들끼리 묶어서 저장 172 | 173 | #### 대체 키 (보조 키) 174 | * 후보 키가 두개 이상일 때, 기본 키를 제외한 나머지 후보 키 175 | 176 | #### 복합 키 177 | * 두개 이상의 컬럼을 묶어서 하나의 기본 키로 지정하는 것 178 | * 기본 키는 하나의 테이블에 하나만 존재할 수 있으며 기본 키는 하나 이상의 컬럼으로 구성 179 | 180 | #### 외래 키 181 | * 한 테이블의 키 중에서 다른 테이블의 튜플을 식별할 수 있는 키 182 | * 참조되는 릴레이션의 `기본 키`와 대응되어 릴레이션 간에 `참조 관계`를 표현하는 키 183 | * 사용 이유: 테이블을 연결, 중복 방지, 무결성 유지 184 | * 예시: 물건 구매시 같은 사람이 여러 물건을 구매하면 사람에 대한 데이터가 중복 -> 사람과 물건 구매로 테이블을 분리해 중복 제거 185 | 186 | 187 |
188 |
189 | 190 | 191 |
192 | 무결성 제약조건 193 |
194 | 195 | * 무결성: 데이터의 정확성, 일관성 196 | * 데이터에 중복/누락이 없음 197 | * 개체 무결성: 주키는 null, 중복 값을 가질 수 없음 198 | * 참조 무결성: 외래키는 null이거나 참조 릴레이션의 기본키 값과 동일해야 함 199 | 200 |
201 |
202 | 203 |
204 | 관계 205 |
206 | 207 | #### 관계 208 | * 테이블 간의 상호작용을 기반으로 설정되는 여러 테이블 간의 논리적 연결 209 | * 주로 외래키(foreign key)를 통해 위 관계를 명시 210 | 211 | #### 1:1 관계 212 | * 하나의 레코드가 다른 테이블의 레코드 한 개와 연결된 경우 213 | * 다른 테이블의 레코드 한 개에만 연결돼야 하므로 자주 사용되진 않음 214 | 215 | #### 1:N 관계 216 | * 하나의 레코드가 다른 테이블의 서로 다른 여러 개의 레코드와 연결된 경우 217 | * 가장 많이 사용되는 관계 218 | 219 | #### N:M 관계 220 | * 관계를 가진 양쪽 테이블에서 1:N 관계를 가진 경우 221 | * 1:N, 1:M 이라는 관계를 갖는 테이블 두개로 니눠서 설정 222 | 223 | #### 관계 표기 방법(ERD) 224 | ![image](https://github.com/yoonje/developer-interview/assets/38535571/503faa2a-41c2-4a0c-a456-ee693c36cfe1) 225 | 226 |
227 |
228 | 229 | 230 |
231 | 트랜잭션 정의 232 |
233 | 234 | * 데이터베이스의 상태를 변화시키는 하나의 `원자적인/논리적인 작업 단위` 235 | * 트랜잭션은 Exclusive Lock 을 발생시키에 Lock과 유사한 기능을 하지만 Lock은 동일한 자원을 요청할 경우 한 시점에는 하나의 커넥션만 변경하는데에 반해 트랜잭션은 논리적인 작업의 쿼리의 개수와 관계없이 논리적인 작업 셋 자체가 `100% 적용되거나 아무것도 적용되지 않아야 함을 보장` 236 | * 주의사항 237 | * 최소한의 코드에 적용하는 것이 좋음 238 | * DB 커넥션의 수는 제한적 -> 커넥션이 부족해 대기할 수 있음 239 | * 트랜잭션 범위를 작게 나눠서 적용해야 DB에 오버헤드가 줄음 240 | 241 |
242 |
243 | 244 | 245 |
246 | 트랜잭션 ACID 247 |
248 | 249 | * 데이터의 유효성을 보장하기 위한 트랜잭션의 특징 250 | * `Atomicity(원자성)`: `모든 작업이 반영되거나 모두 롤백되는 특성`입니다. 251 | * `Consistency(일관성)`: 데이터는 `미리 정의된 규칙에서만 수정이 가능한 특성`을 의미합니다. 252 | * 도메인, 외래키 관게 유지 253 | * `Isolation(고립성)`: 두 개 이상의 트랜잭션이 동시에 발생할 때, 서로의 연산에 영향을 줄 수 없음 254 | * Lock으로 보장 255 | * `Durability(영구성)`: 한번 반영(커밋)된 트랜젝션의 내용은 `영원히 적용`되는 특성을 의미합니다. 256 | 257 |
258 |
259 | 260 | 261 |
262 | 트랜잭션 격리수준 263 |
264 | 265 | #### 트랜잭션 격리수준 266 | * 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경/조회하는 데이터에 대한 접근 권한 수준을 결정하는 것 267 | * 일관성 없는 데이터를 허용하도록 하는 수준 268 | * ACID를 희생하고 동시성을 높이는 방법 269 | * 레벨이 낮을수록 동시성은 높음, 무결성은 하락 270 | 271 | #### 필요성 272 | * 락으로 모든 트랜잭션이 순서대로 처리하도록 하면 DB의 성능이 떨어짐 273 | 274 | #### 종류 275 | ##### Read Uncommitted (레벨 0) 276 | * Select를 수행할 때 해당 데이터에 Shared Lock이 걸리지 않는 레벨 277 | * Commit되지 않은 데이터를 읽을 수 있음 278 | * 일관성 유지가 거의 불가능 279 | ##### Read Committed (레벨 1) 280 | * SELECT를 수행하는 동안 해당 데이터에 Shared Lock이 걸리는 레벨 281 | * 커밋된 내용만 접근 가능 282 | ##### Repeatable Read (레벨 2) 283 | * 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 레벨 284 | * 트랜잭션 범위 내에서 조회한 데이터는 항상 동일 285 | * 트랜잭션에 진입하기 이전에 커밋된 내용만 접근 가능 286 | * 데이터 추가는 허용, 변경/삭제는 허용하지 않음 287 | ##### Serializable (레벨 3) 288 | * 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 레벨 289 | * 트랜잭션 범위 내에서 조회한 데이터는 항상 동일 290 | * 완벽한 읽기 일관성을 제공함 291 | * 데이터의 추가/변경/삭제 불가능 292 | 293 | #### 참고: Lock 294 | * 공유락(Shared Lock): `Select`에 의해 설정, 데이터를 다른 트랜잭션이 읽기 허용, 쓰기 불허용 295 | * 베타락(Exclusive Lock): `INSERT`, `UPDATE`, `DELETE`에 의해 설정, 데이터를 다른 트랜잭션이 읽기, 쓰기 모두 불허용 296 |
297 |
298 | 299 | 300 |
301 | 인덱스 정의 302 |
303 | 304 | * `추가적인 쓰기와 저장 공간` 사용을 통해 `검색 속도 향상`을 위해 사용하는 자료구조 305 | * 칼럼의 `값`과 해당 레코드가 저장된 `주소`를 `키와 값의 쌍`으로 인덱스 정의 306 | 307 |
308 |
309 | 310 |
311 | 인덱스 장단점 312 |
313 | 314 | #### 장점 315 | * 검색 속도 향상 316 | 317 | #### 단점 318 | * 데이터의 추가, 삭제, 수정의 경우 인덱스도 변경해야 하여 성능이 오히려 저하될 수 있음 (정렬 상태를 계속 유지해야 함) 319 | * 추가적인 저장 공간 필요 및 성능 저하 320 | * 복합 키나 복합 인덱스의 경우 컬럼 순서가 맞지 않아서 인덱스를 타지 못하거나 칼럼의 값에 따라 인덱스의 위치가 변화될 수 있어 문제를 유발할 수 있음 321 | 322 |
323 |
324 | 325 |
326 | 복합 인덱스 효과적으로 달기 327 |
328 | 329 | * 여러 필드를 기반으로 조회할 때 복합 인덱스를 생성 330 | * 생성 순서에 따라 성능이 달라지는데 순서는 `같음`, `정렬`, `부호(> or <)`, `카디널리티` 순으로 생성해야함 331 | 332 |
333 |
334 | 335 |
336 | 인덱스 자료구조: 트리 337 |
338 | 339 | #### B 트리 340 | 341 | ![tree](https://user-images.githubusercontent.com/38900338/105454677-9bf88400-5cc5-11eb-993e-fb6f7b9675a1.png) 342 | * 이진 트리를 확장해서, 더 많은 수의 자식을 가질 수 있게 일반화 시킨 자료구조 343 | * 균형 트리: 루트 ~ 리프의 거리가 일정한 트리 344 | * Branch 노드: Key와 Data 저장 345 | 346 | #### B+ 트리 347 | 348 | ![Bplustree](https://user-images.githubusercontent.com/38900338/105454222-d9104680-5cc4-11eb-96e9-31e46c0bf2aa.png) 349 | 350 | * B 트리를 확장해서, 데이터의 빠른 접근을 위한 인덱스 역할만 하는 비단말 노드(not Leaf)를 추가한 자료구조 351 | * Branch 노드: Key만 저장, Leaf 노드: Key와 Data 저장 + Linked List로 연결(부등호를 사용한 순차 검색에 유용) 352 | * B 트리보다 풀 스캔 빠름 353 | * Leaf 노드를 제외하면 데이터를 저장하지 않아 더 많은 Key를 저장할 수 있음 -> 트리의 높이가 낮아져 Cache Hit 향상 가능 354 | 355 |
356 |
357 | 358 | 359 |
360 | 인덱스 자료구조: 해시 테이블 361 |
362 | 363 | * 칼럼의 값으로 생성된 해시를 기반으로 인덱스 구현 364 | * O(1)로 매우 빠름 365 | * `부등호` 연산 때문에 성능이 떨어짐 366 | * `>=, Between, like, order by` 등은 불가능하지만 `==, in, is null` 등에서의 성능은 좋음 367 | 368 |
369 |
370 | 371 |
372 | Clustered Index vs Non Clustered Index 373 |
374 | 375 | #### Clustered Index 376 | * 인덱스로 지정한 컬럼을 기준으로 데이터를 `물리적으로 정렬`하여 사용하는 인덱스 377 | * 테이블 구조에 영향을 미치는 인덱스 378 | * 한 테이블에 `1개` 생성 가능 379 | * 기본키는 클러스터형 인덱스 380 | * 비클러스터형 인덱스보다 `검색 속도는 빠르지만`, 데이터의 입력/수정/삭제는 느림 381 | * 일반적으로 PK를 Clustered Index라고 부름 382 | 383 | #### Non-Clustered Index 384 | * 데이터를 물리적으로 재배열 하지 않고 인덱스 페이지만 정렬하여 사용하는 인덱스 385 | * 한 테이블에 `여러 개` 생성 가능 386 | * 클러스터형 인덱스보다 `검색 속도는 느리지만`, 데이터의 입력/수정/삭제는 빠름 387 | * 일반적으로 생성하는 인덱스는 모두 Non-Clustered Index라고 부름 388 | 389 |
390 |
391 | 392 | 393 |
394 | 정규화 395 |
396 | 397 | ### 정의 398 | * 데이터의 중복을 제거해 데이터 무결성을 유지하는 것 399 | * 속성 간의 종속성으로 인한 `이상현상`을 `테이블을 분해`해 해결하는 것 400 | * 이상현상 (Anomaly): 테이블 내의 데이터가 중복되어 테이블을 조작할 때 발생하는 데이터 불일치 401 | * 테이블의 속성들이 상호 종속적인 관계를 갖는 특성을 이용하여 테이블을 `무손실 분해` 하는 과정 402 | * 무손실 분해: 하나의 릴레이션을 분해하고 다시 조인연산을 했을 때 데이터 손실이 없는 것, 분해된 테이블이 표현하는 정보는 분해되기 전의 정보를 모두 포함 403 | 404 | ### 목적 405 | * 데이터 `중복 최소화`, 불필요한 데이터 최소화 406 | * `무결성` 유지, `이상 현상` 방지 407 | * 테이블의 구성을 논리적/직관적으로 수정 408 | 409 | ### 종류 410 | 411 | #### 제 1 정규화 (1NF) 412 | * 테이블 컬럼이 `원자 값`을 갖도록 분해 413 | * 모든 필드가 원자 값으로만 되어 있어야 함 414 | 415 | #### 제 2 정규화 (2NF) 416 | * 테이블의 모든 컬럼이 `완전 함수 종속`을 만족하도록 분해 417 | * 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속 418 | * 기본키를 구성하는 속성 중 일부에 종속되지 않음 419 | * 테이블에서 기본키가 복합키(키1, 키2)로 묶여있을 때, 두 키 중 하나의 키만으로 다른 컬럼을 결정지을 수 있으면 안됨 420 | * 기본키의 부분집합이 결정자가 되면 안됨 421 | 422 | ##### 함수적 종속 423 | * X -> Y: X = 결정자, Y = 종속자 (Y는 X에 함수적 종속, X/Y는 속성의 부분집합) 424 | * X의 값을 알면 Y를 식별할 수 있고, X의 값에 Y의 값이 달라짐 425 | 426 | #### 제 3 정규화 (3NF) 427 | * 기본키가 아닌 모든 컬럼이 기본키에 `비이행적 종속(직접 종속)`하도록 분해 428 | * 기본키가 아닌 컬럼이 다른 컬럼을 결정할 수 없음 429 | 430 | ##### 이행적 함수 종속 431 | * X, Y, Z 속성에 대해 X->Y 이고 Y->Z 이면 X->Z 432 | 433 | #### BCNF (Boyce and Codd Normal Form) 434 | * 모든 결정자가 `후보키`가 되도록 분해 435 | * 함수 종속성 X->Y일 때, 모든 결정자 X가 후보키 436 | * 일반 튜플이 후보키를 결정지으면 안됨 437 | 438 |
439 |
440 | 441 |
442 | 반정규화 443 |
444 | 445 | ### 정의 446 | * 데이터베이스의 성능 향상을 위하여, 데이터 중복을 허용하고 `조인을 줄이는 방법` 447 | 448 | ### 목적 449 | * 정규화에 충실하여 종속성, 활용성은 향상 되었지만 수행 속도가 느려지는 것을 막음 450 | * 조회 속도를 향상시키지만, 데이터 모델의 유연성은 낮아짐 451 | * Join 이 3번이상 발생한다면, 이건 시스템 장애를 일으킬 수 있는 쿼리일 수 있으므로 반정규화를 고려 452 | 453 |
454 |
455 | 456 | 457 |
458 | 파티셔닝 459 |
460 | 461 | ### 정의 462 | * `하나의 DB`에서 데이터를 물리적으로 분할하는 것 463 | 464 | ### 장단점 465 | * 큰 테이블을 제거하여 관리가 쉬움 466 | * DML 성능 향상: 접근하는 데이터 수 감소, 인덱스 크기 감소 467 | * 조인 비용 증가 468 | * 테이블과 인덱스를 별도로 파티셔닝 할 수 없고 함께 파티셔닝 해야 함 469 | 470 | ### 분할 방법 471 | #### 수평 분할 (Horizontal Partitioning) 472 | * `하나의 DB`안에 `스키마가 같은` 데이터를 두 개 이상의 테이블에 분할하여 저장 473 | * 예시 474 | * 주민 테이블 -> a동 테이블, b동 테이블로 분리 475 | 476 | #### 수직 분할 (Vertical Partitioning) 477 | * 테이블을 열을 기준으로 분리 478 | * 정규화된 테이블을 분리하는 것 479 | 480 |
481 |
482 | 483 |
484 | 샤딩 485 |
486 | 487 | * `여러 DB`에 데이터를 물리적으로 `수평 분할 방식(Horizontal Partitioning)`으로 분산 저장/조회하는 것 488 | * `트래픽 분산` 목적으로 사용: 데이터베이스에 데이터 증가 -> 용량 이슈, CRUD 성능 저하 489 | * 쿼리 성능 향상 490 | * 복잡도 증가, Hotspot이 생기면 샤딩 무의미 해짐 491 | * 두 개 이상의 샤드에서 `JOIN 불가`, 일관성과 복제에서 불리 492 | * 예시 493 | * 주민 테이블 -> a동 테이블은 A DB, b동 테이블은 B DB에 저장 494 | 495 |
496 |
497 | 498 |
499 | 레플리카 500 |
501 | 502 | * `동일한 데이터를 Master/Slave DB로 나누어 저장`하는 것 (이중화) 503 | * 목적 504 | * 읽기(Slave)와 쓰기(Master) DB를 분리하여 성능을 향상시킴 505 | * 많은 Slave를 생성해 읽기 성능을 향상시킬 수 있음 506 | 507 |
508 |
509 | 510 | 511 |
512 | 클러스터링과 리플리케이션의 차이 513 |
514 | 515 | #### 클러스터링 516 | * DB를 `수평` 구조로 다중화 517 | * Fail Over 시스템 구축을 위해 사용 518 | * 동기 방식으로 동기화 -> 항상 일관성 유지, 동기화 시간 소요 519 | * 1개 DB가 고장나도 시스템 계속 운영 가능 520 | * Active - Active, Active - Standby 521 | 522 | #### 리플리케이션 523 | * DB를 `수직` 구조인 Master와 Slave로 다중화 524 | * Master는 쓰기, Slave는 읽기만 수행 -> 부하 분산 525 | * 비동기 방식으로 동기화 -> 시간 지연 거의 없음 526 | * Master 오류시 복구 어려움 527 | 528 |
529 |
530 | 531 | 532 |
533 | SQL Injection 534 |
535 | 536 | * 해커에 의해 조작된 SQL 쿼리문이 데이터베이스에 그대로 전달되어 비정상적인 명령을 실행시키는 공격 기법 537 | * 입력값 검증 538 | * Prepared Statement 사용: 쿼리에 대한 컴파일을 먼저 수행하고, 입력값을 나중에 넣는 방식 539 | * 바인딩 변수: 삽입되는 데이터는 문자열로 취급되어 SQL의 역할을 하지못함 540 | 541 |
542 |
543 | 544 | 545 |
546 | 힌트(Hint) 547 |
548 | 549 | * SQL을 `튜닝`하기 위한 지시 구문, 개발자가 직접 최적의 실행 계획을 제공하는 것 550 | 551 |
552 |
553 | 554 | 555 |
556 | 시퀀스 557 |
558 | 559 | * `순차적으로 증가하는 숫자를 생성`하는 객체 560 | * `기본 키`와 같은 유일한 숫자를 자동으로 생성하는 것 561 | * 캐시에 있어 속도 빠름, 중복 방지에 사용 562 | 563 |
564 |
565 | 566 | 567 |
568 | 트리거 569 |
570 | 571 | * DML이 수행되었을 때, 자동으로 실행되게 정의한 프로시저 572 | * DML(INSERT, UPDATE, DELETE)에 의한 데이터 상태관리 자동화 573 | * 데이터 무결성 강화, 업무 처리 자동화 574 | 575 |
576 |
577 | 578 | 579 | 580 |
581 | 커넥션 풀 582 |
583 | 584 | * `미리 일정 수의 Connection을 만들어 pool에 보관 -> 사용자의 요청이 발생하면 연결을 해주고 연결 종료 시 pool에 다시 반환하여 보관하는 것` 585 | * 사용자의 요청에 따라 Connection 을 생성하다 보면 많은 수의 연결이 발생했을 때 서버에 과부하가 걸리게 되므로 이러한 상황을 방지하기 위해 사용 586 | * 커넥션 풀을 사용하면 커넥션을 생성하고 닫는 시간이 소모되지 않기 때문에 그만큼 어플리케이션의 `실행 속도가 빨라짐` 587 | * 한 번에 생성될 수 있는 커넥션 수를 제어하기 때문에 동시 접속자 수가 몰려도 웹 어플리케이션이 쉽게 다운되지 않음 588 | 589 |
590 |
591 | 592 |
593 | Redis와 MongoDB 594 |
595 | 596 | * Redis는 NoSQL 방식을 사용하는 인메모리 데이터베이스로 `Key-Value` 형식으로 데이터를 저장하며 주로 캐쉬로 사용 597 | * MongoDB는 NOSQL 방식을 사용하는 데이터베이스로 JSON같은 구조의 `Document` 형식으로 데이터를 저장하고 문서에 대한 ID를 키로 표현 598 | 599 |
600 |
601 | 602 |
603 | Redis의 데이터 휘발을 막기 위한 방법 604 |
605 | 606 | * `snapshot` 기능을 통해 디스크에 백업하거나 `AOF(Append Only File)` 기능을 통해 `명령 쿼리를 저장`해두고 서버가 셧다운 되면 재실행 607 | * snapshot: 특정 시점의 백업 및 복구에 유리, 빠르게 복구 가능, 서버가 다운되면 스냅샷 사이에 변경된 데이터 유실 608 | * AOF: 모든 write/update 연산 자체를 모두 log 파일로 기록, 서버가 실행되면 순차적으로 연산을 재실행하여 데이터를 복구, write 속도 빠름, 데이터 유실X, 데이터 사용량이 큼, 서버 restart 시 속도 느림 609 | 610 |
611 |
612 | 613 |
614 | PostgresSQL과 ElasticSearch의 차이점 615 |
616 | 617 | * PostgresSQL은 관계형 데이터베이스이고 ElasticSearch는 검색 및 분석엔진 618 | * ES는 데이터 모델을 JSON으로 하고 있어 NoSQL처럼 사용할 수 있음 619 | 620 |
621 |
622 | -------------------------------------------------------------------------------- /Datastructure/README.md: -------------------------------------------------------------------------------- 1 | # Data Structure 2 | 3 |
4 | 5 |
6 | 배열과 연결 리스트 7 |
8 | 9 | #### 배열 (Array) 10 | * `메모리에 연속적으로 데이터를 저장하는` 자료구조 11 | * `탐색 O(1)`: 인덱스를 사용해 `Random Access` 가능 12 | * `삽입/삭제 O(N)`: 삽입/삭제한 원소보다 큰 인덱스를 갖는 원소들을 `Shift`해야 함 13 | * `크기 고정적` (선언 시 지정한 크기 변경 불가): `Immutable` 14 | * Cache Locality가 좋아 Cache Hit 가능성이 큼 15 | 16 | #### 연결 리스트 (Linked List) 17 | * `메모리가 불연속적`으로 배치된 자료구조 18 | * 다음 노드를 가리키는 `주소인 포인터`를 통해 접근하는 자료구조 (자료의 주소 값으로 서로 연결) 19 | * `탐색 O(N)`: 데이터 검색 시 처음 노드부터 순회하는 `순차 접근` 20 | * `삽입/삭제 O(1)`: 주소의 연결만 바꾸면 됨 -> 하지만, 삽입/삭제할 원소를 찾는 것에 O(N)이 걸림 21 | 22 | 23 | #### 배열 리스트와 연결 리스트 비교 24 | * 삽입/삭제가 많은 경우 -> LinkedList가 좋음 25 | * 데이터 접근이 많은 경우 -> Array가 좋음 26 |
27 |
28 | 29 |
30 | 해시테이블 31 |
32 | 33 | #### 해시 테이블 34 | * `Key와 Value`로 데이터를 저장하는 자료구조 35 | * `key 값`을 통해 해시 주소를 알아내어 평균적으로 탐색에 `O(1)`을 보장하는 자료구조 36 | * Key에 `해시 함수`를 적용해 고유한 인덱스(`해시 값`)를 생성하고, 이 인덱스를 활용해 값을 저장/검색 37 | * 실제 값이 저장되는 장소를 버킷(슬롯)이라고 함 38 | * 많은 데이터를 효율적으로 관리하기 위해 하드디스크나, 클라우드에 존재하는 무한한 데이터들을 유한한 개수의 해시값으로 매핑하면 작은 메모리로도 프로세스 관리가 가능해져서 사용함 39 | 40 | #### 해시 함수 41 | * 임의의 길이의 데이터를 수학적 연산을 통해 `고정된 길이의 데이터로 매핑`하는 함수 42 | * 해시 함수에 의해 얻어지는 값을 `해시`라고 함 43 | 44 | #### 해시 충돌과 해결 방법 45 | * `서로 다른 key가 같은 해시 값으로 변경`되는 것 46 | * 같은 해시 값에 대해 데이터를 조회해 탐색에 최대 `O(N)` 가능 47 | * `체이닝`: 추가 메모리를 사용해 버킷에 데이터를 `연결 리스트`로 관리 48 | * `개방 주소법`: 기존의 비어있는 버킷의 공간을 활용 49 | * 선형 조사법(Linear Probing): 현재 버킷의 인덱스에서 `고정 폭`씩 이동하며 데이터를 버킷에 저장 50 | * 이차 조사법(Quadratic Probing): 현재 버킷의 인덱스에서 `k^2`(k=1, 2, ..)씩 이동하며 데이터를 버킷에 저장 51 | * 이중 해싱(Double Hashing Probing): 해싱된 값을 한번 더 해싱 -> 연산 증가 52 | 53 | 54 |
55 |
56 | 57 |
58 | 스택과 큐 59 |
60 | 61 | #### 스택 (Stack) 62 | * `LIFO(Last In First Out)` 방식으로 삽입되고 제거되는 `최근성`에 포커싱된 자료구조 63 | * Array로 구현하는 것이 좋음 64 | 65 | #### 큐 (Queue) 66 | * `FIFO(First In First Out)` 방식으로 삽입되고 제거되는 `순차성`에 포커싱된 자료구조 67 | * Linked List로 구현하는 것이 좋음 68 |
69 |
70 | 71 |
72 | 트리 73 |
74 | 75 | #### 트리 76 | * `사이클을 가지지 않는 그래프` (비선형 자료구조) 77 | * 부모 자식 관계를 갖는 `계층적` 구조를 갖는 자료구조 78 | * `이진 트리(Binary Tree)`: 최대 2개의 자식 노드들만 가질 수 있는 트리 79 | * `포화 이진 트리(Perfect Binary Tree)`: 각 레벨에 노드가 꽉 차있는 트리 80 | * `완전 이진 트리(Complete Binary Tree)`: 높이가 K인 트리에서 레벨 1~K-1까지 모두 채워져 있고 마지막 레벨에서는 왼쪽부터 순서대로 채워져 있는 트리 81 | * `이진 탐색 트리(Binary Search Tree)`: 탐색을 위해 만들어진 자료구조로 `부모 노드의 키 값이 왼쪽 자식 노드의 키 값보다 크고 오른쪽 자식 노드의 키 값보다 작은` 트리 82 | #### 트리 순회 83 | * 중위 순회: 왼 -> 루트 -> 오른 84 | * 전위 순회: 루트 -> 왼 -> 오른 85 | * 후위 순회: 왼 -> 오른 -> 루트 86 | 87 |
88 |
89 | 90 |
91 | 92 |
93 | 94 | #### 힙 95 | * `완전 이진 트리`의 일종으로 `우선 순위 큐`를 구현하기 위해 만들어진 자료구조 96 | * `최소값 또는 최대값`을 쉽게 찾기 위한 자료구조 (이진 탐색 트리가 전체 노드를 탐색하기 위한 자료구조) 97 | * 힙은 중복 값 허용 (이진 탐색 트리는 중복값 허용X) 98 | * `부모 노드의 키 값이 자식 노드의 키 값보다 항상 큰/작은 완전 이진 트리`로 힙은 자식 노드에도 구분 조건이 필요한 이진 탐색 트리보다 `느슨한 정렬` 상태를 유지 99 | 100 | #### 힙 (Heap) 101 | * `완전 이진 트리`의 일종으로 `우선 순위 큐`를 구현하기 위해 만들어진 자료구조 102 | * `최소값 또는 최대값`을 쉽게 찾기 위한 자료구조 (이진 탐색 트리가 전체 노드를 탐색하기 위한 자료구조) 103 | * 힙은 중복 값 허용 (이진 탐색 트리는 중복값 허용X) 104 | * `부모 노드의 키 값이 자식 노드의 키 값보다 항상 큰/작은 완전 이진 트리`로 힙은 자식 노드에도 구분 조건이 필요한 이진 탐색 트리보다 `느슨한 정렬` 상태를 유지 105 | 106 | #### 최대 힙 107 | * `부모 노드의 키 값이 자식 노드의 키 값보다 크거나 같은` 완전 이진 트리 108 | * 부모가 최대값 109 | #### 최소 힙 110 | * `부모 노드의 키 값이 자식 노드의 키 값보다 작거나 같은` 완전 이진 트리 111 | * 부모가 최소값 112 | 113 | #### 시간 복잡도 114 | * 원소 삽입: `O(logn)` 115 | * 새로운 노드를 힙의 마지막 노드에 삽입 -> 새로운 노드를 부모 노드들과 교환 116 | * 원소 삭제: `O(logn)` 117 | * 루트 노드 삭제 -> 삭제된 루트에 힙의 마지막 노드를 가져옴 -> 재구성 118 | 119 |
120 |
121 | 122 | 123 |
124 | 이진 탐색 트리 125 |
126 | 127 | #### 이진 탐색 트리 (Binary Search Tree) 128 | * 노드의 `왼쪽 서브 트리에는 그 노드의 값보다 작은 값들`을 지닌 노드들로 구성, `오른쪽 서브 트리에는 그 노드의 값보다 큰 값들`을 지닌 노드들로 구성 129 | * `중위 순회`: 검색 시 내려가면서 해당 노드보다 찾는 값이 더 작으면 왼쪽에서 찾고, 찾는 값이 더 크면 오른쪽에서 찾음 130 | * 중복 값을 가지지 않음 131 | 132 | #### 이진 탐색 트리의 시간 복잡도 133 | * 탐색/삽입/삭제 평균 시간복잡도: `O(logN)` 134 | * 탐색/삽입/삭제 최악 시간복잡도: `한쪽으로만 삽입된 경우 O(N)` 135 | * 시간복잡도는 `트리의 Depth에 비례` 136 | * 최악의 경우를 방지하는 방법: `자가 균형 트리(Balanced Tree)` 137 | * `AVL 트리`: 왼쪽과 오른쪽 자식의 높이 차이가 1이하일 것을 요구, 삭제/추가 시에 재정렬(회전)을 통해 높이를 일정하게 유지, 레드 블랙 트리보다 엄격, 평균/최악 시간복잡도 `O(logN)` 138 | * `레드 블랙 트리`: 모든 노드가 빨강 또는 검정의 색을 갖는 트리로 루트부터 리프까지의 최장 경로는 최단 경로의 두 배 이상이 될 수 없음, 루트부터 리프까지의 검은색 노드 수가 모드 같음, 삭제/추가 시에 재정렬과 색깔 재배치를 통해 규칙을 유지 139 | 140 |
141 |
142 | 143 |
144 | 그래프 145 |
146 | 147 | #### 그래프 (Graph) 148 | * 정점과 간선으로 이루어진 자료구조 149 | 150 | #### 구현 방법과 장단점 151 | * `인접 행렬` 사용: 2차원 배열을 사용해 정점들의 연결관계를 파악하는 방법으로, 시간 복잡도 `O(1)`로 연결 관계를 파악할 수 있음, `정점과 엣지가 많을 경우 사용`, 구현 간편, 공간 낭비 152 | * `인접 리스트` 사용: 각 정점의 adjacent list를 통해서 연결 관계를 파악하는 방법으로, 정점들의 관계를 `O(정점에 연결된 노드의 수)`로 파악하는 방법, `정점과 엣지가 적을 경우 사용`, 공간 낭비 적음, 탐색 시간이 느림, 구현 어려움 153 |
154 |
155 | 156 | 157 |
158 | Cache Locality 159 |
160 | 161 | #### Cache Locality 162 | * 시간 지역성: 최근에 접근한 데이터는 빠르게 다시 접근할 수 있음 (for, while 반복문) 163 | * 공간 지역성: 참조된 데이터 근처에 있는 데이터가 잠시 후에 사용될 가능성이 높음 164 | * 배열은 물리적으로 연속된 공간에 데이터를 저장하여 공간 지역성이 좋음 165 | * Cache hit: 지역성을 활용하기 위해 캐쉬에 저장해놓은 메모리에 CPU가 참조하고자 하는 메모리가 있다면 cahce hit, 반대는 cache miss 166 |
167 |
168 | -------------------------------------------------------------------------------- /DesignPattern/README.md: -------------------------------------------------------------------------------- 1 | # Design Pattern 2 | 3 |
4 | 5 |
6 | 디자인 패턴 7 |
8 | 9 | * 소프트웨어 코드 작성 시에 생기는 `공통적인 문제를 해결하는데 도움이 되는 코드 패턴` 10 | * 디자인 패턴은 객체 지향의 특성 중 상속, 인터페이스, 객체를 속성으로 사용하는 것을 이용해 구현 11 | 12 |
13 |
14 | 15 |
16 | 디자인 패턴 종류 17 |
18 | 19 | * 생성 패턴: 객체 `생성`에 관련된 패턴 20 | * 팩토리 메서드 패턴(Factory Method Pattern): 어떤 클래스의 인스턴스를 만들지는 서브 클래스에서 결정하는 패턴 21 | * 싱글턴 패턴(Singleton Pattern): 오직 인스턴스를 하나만 만들어서 재사용하는 패턴 22 | * 빌더 패턴(Builder Pattern): 생성(construction)과 표기(representation)를 분리해 복잡한 객체를 생성하는 패턴 23 | * 구조 패턴: `클래스나 객체를 조합해 더 큰 구조를 만드는 패턴` 24 | * 데코레이터 패턴(Decorator Pattern): 원본에 장식을 더하는 데커레이터를 통해서 객체의 결합을 통해 반환 값에 장식을 덧붙이는 패턴 25 | * 프록시 패턴(Proxy Pattern): 대신해서 그 역할 수행하는 프록시를 통해서 메서드의 반환 값을 수정하는 게 아니라 별도 로직을 수행하는 패턴 26 | * 어댑터 패턴(Adapter Pattern): 객체를 속성으로 참조해서 만드는 패턴으로 호출 당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 변환기를 통해 호출하는 패턴 27 | * 행위 패턴: 클래스나 객체들이 서로 `상호 작용하는 방법이나 책임 분배 방법을 정의하는 패턴` 28 | * 옵서버 패턴(Observer Pattern): 한 객체의 상태 변화를 관찰하다가 변화가 있을 때마다 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 패턴으로 일대다 객체 의존 관계를 구성하는 패턴 29 | * 템플릿 메서드 패턴(Template Method Pattern): 상위 클래스의 템플릿 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴 30 | * 전략 패턴(Strategy Pattern): 클라이언트가 전략을 생성해 전략을 실행한 컨텍스트에 주입하는 패턴 31 | 32 |
33 |
34 | 35 | 36 |
37 | 싱글톤 패턴 38 |
39 | 40 | * 오직 인스턴스를 하나만 만들어서 재사용하는 패턴(생성 패턴) 41 | * 한번의 객체 생성으로 `재사용`이 가능하기 때문에 메모리 낭비를 방지하고 객체가 `전역성`을 띄기 때문에 공유가 용이 42 | * 예시 43 | ```java 44 | public class Singleton { 45 | 46 | static Singleton singletonObject; 47 | 48 | private Singleton() {}; 49 | 50 | public static Singleton getInstance() { 51 | if (singleObject == null) { 52 | singletonObject = new Singleton(); 53 | } 54 | return singletonObject; 55 | } 56 | } 57 | ``` 58 |
59 |
60 | 61 | 62 |
63 | 팩토리 메서드 패턴 64 |
65 | 66 | * 하위 클래스에서 객체를 생성 반환에 사용되는 메서드인 팩터리 메서드를 오버라이딩해서 객체를 반환하게 하는 패턴(생성 패턴) 67 | * 팩토리 패턴은 클래스의 `인스턴스를 만드는 것을 서브 클래스에서 결정하는 패턴`으로 팩토리 메서드 패턴과 추상 팩토리 패턴으로 구체화되나 주로 팩토리 메서드 패턴를 사용 68 | * 예시 69 | ```java 70 | abstract class Coffee { 71 | 72 | // 팩터리 메서드 73 | public abstract int getPrice(); 74 | 75 | @Override 76 | public String toString() { 77 | return "Hi this coffee is " + this.getPrice(); 78 | } 79 | } 80 | ``` 81 | ```java 82 | class CoffeeFactory { 83 | public static Coffee getCoffee(String type, int price) { 84 | if ("Latte".equalsIgnoreCase(type)) 85 | return new Latte(price); 86 | else if ("Americano".equalsIgnoreCase(type)) 87 | return new Americano(price); 88 | else { 89 | return new DefaultCoffee(); 90 | } 91 | } 92 | } 93 | ``` 94 | ```java 95 | class Americano extends Coffee { 96 | private int price; 97 | 98 | public Americano(int price) { 99 | this.price = price; 100 | } 101 | 102 | @Override 103 | public int getPrice() { 104 | return this.price; 105 | } 106 | } 107 | ``` 108 | ```java 109 | class Latte extends Coffee { 110 | private int price; 111 | 112 | public Latte(int price) { 113 | this.price = price; 114 | } 115 | 116 | @Override 117 | public int getPrice() { 118 | return this.price; 119 | } 120 | } 121 | ``` 122 | ```java 123 | public class TestApplication { 124 | public static void main(String[] args) { 125 | Coffee latte = CoffeeFactory.getCoffee("Latte", 4000); 126 | Coffee americano = CoffeeFactory.getCoffee("Americano", 3000); 127 | System.out.println("Factory latte ::" + latte); 128 | System.out.println("Factory americano ::" + americano); 129 | } 130 | } 131 | ``` 132 |
133 |
134 | 135 |
136 | 빌더 패턴 137 |
138 | 139 | * 생성(construction)과 표기(representation)를 분리해 복잡한 객체를 생성하는 패턴(생성 패턴) 140 | * 복잡한 객체의 생성의 경우에 유용 141 | * 예시 142 | ```java 143 | public class Industry { 144 | 145 | private String id; 146 | private String code; 147 | private String name; 148 | private Area area; 149 | 150 | public String getCode() { 151 | return code; 152 | } 153 | 154 | public void setCode(String code) { 155 | this.code = code; 156 | } 157 | 158 | public String getName() { 159 | return name; 160 | } 161 | 162 | public void setName(String name) { 163 | this.name = name; 164 | } 165 | 166 | public String getId() { 167 | return id; 168 | } 169 | 170 | public void setId(String id) { 171 | this.id = id; 172 | } 173 | 174 | public Area getArea() { 175 | return area; 176 | } 177 | 178 | public void setArea(Area area) { 179 | if (area.isValid()) { 180 | this.area = area; 181 | } else { 182 | throw new IllegalArgumentException(grade); 183 | } 184 | } 185 | 186 | public static final class Builder { 187 | private String id; 188 | private String code; 189 | private String name; 190 | private Area area; 191 | 192 | public Builder() { 193 | } 194 | 195 | public static Builder industry() { 196 | return new Builder(); 197 | } 198 | 199 | public Builder id(String id) { 200 | this.id = id; 201 | return this; 202 | } 203 | 204 | public Builder code(String code) { 205 | this.code = code; 206 | return this; 207 | } 208 | 209 | public Builder name(String name) { 210 | this.name = name; 211 | return this; 212 | } 213 | 214 | public Builder area(Area area) { 215 | this.area = area; 216 | return this; 217 | } 218 | 219 | public Industry build() { 220 | Industry industry = new Industry(); 221 | industry.setId(id); 222 | industry.setCode(code); 223 | industry.setName(name); 224 | industry.setArea(area); 225 | return industry; 226 | } 227 | } 228 | } 229 | ``` 230 |
231 |
232 | 233 |
234 | 프록시 패턴 235 |
236 | 237 | * 대신해서 그 역할 수행하는 프록시를 통해서 메서드의 반환 값을 수정하는 게 아니라 별도 로직을 수행하는 패턴(구조 패턴) 238 | * 예시 239 | ```java 240 | public interface IService { 241 | String runSomething(); 242 | } 243 | ``` 244 | ```java 245 | public class ServiceA implements IService { 246 | public String runSomething() { 247 | return "서비스"; 248 | } 249 | } 250 | ``` 251 | ```java 252 | public class Proxy implements IService { 253 | IService service; 254 | 255 | public String runSomething() { 256 | System.out.println("호출에 대한 흐름 제어가 목적, 반환 값은 그대로"); 257 | service = new ServiceA(); 258 | return service.runSomething(); 259 | } 260 | } 261 | ``` 262 | ```java 263 | public class ClientWithProxy { 264 | // 프록시를 이용한 호출 265 | IService proxy = new Proxy(); 266 | System.out.println(proxy.runSomething()); 267 | } 268 | ``` 269 |
270 |
271 | 272 |
273 | 데코레이터 패턴 274 |
275 | 276 | * 원본에 장식을 더하는 데커레이터를 통해서 객체의 결합을 통해 반환 값에 장식을 덧붙이는 패턴(구조 패턴) 277 | * 장식자의 역할은 원본에 장식을 더하는 것 278 | * 예시 279 | ```java 280 | public interface IService { 281 | String runSomething(); 282 | } 283 | ``` 284 | ```java 285 | public class ServiceA implements IService { 286 | public String runSomething() { 287 | return "서비스"; 288 | } 289 | } 290 | ``` 291 | ```java 292 | public class Decorator implements IService { 293 | 294 | IService serivce; 295 | 296 | public String runSomething() { 297 | System.out.println("호출에 대한 장식이 주목적, 반환 값에 장식을 더함"); 298 | service = new ServiceA(); 299 | return "정말" + service.runSomething(); 300 | } 301 | } 302 | ``` 303 | ```java 304 | public class ClientWithDecorator { 305 | 306 | public statis void mian(String[] args) { 307 | // 데코레이터를 이용한 호출 308 | IService decorator = new Decorator(); 309 | System.out.println(decorator.runSometing()); 310 | } 311 | } 312 | ``` 313 | 314 |
315 |
316 | 317 |
318 | 어댑터 패턴 319 |
320 | 321 | * 객체를 속성으로 참조해서 만드는 패턴으로 호출 당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 변환기를 통해 호출하는 패턴(구조 패턴) 322 | * 어댑터(변환기)의 역할은 서로 다른 두 인터페이스 사이에 통신이 가능하게 하는 것 323 | * 예시 324 | ```java 325 | public class AdapterServiceA { 326 | 327 | ServiceA sa1 = new ServiceA(); 328 | 329 | void run() { 330 | sa1.runA(); 331 | } 332 | } 333 | ``` 334 | ```java 335 | public class AdapterServiceB { 336 | 337 | ServiceB sb1 = new ServiceB(); 338 | 339 | void run() { 340 | sb1.runB(); 341 | } 342 | } 343 | ``` 344 | ```java 345 | public class ClientWithAdapter { 346 | 347 | public static void main(String[] args){ 348 | 349 | AdapterServiceA asa1 = new AdapterServiceA(); 350 | AdapterServiceB asb1 = new AdapterServiceB(); 351 | 352 | // 어댑터에 의해 래핑되어 동일한 메서드 명 사용 353 | asa1.run(); 354 | asb1.run(); 355 | } 356 | } 357 | ``` 358 |
359 |
360 | 361 |
362 | 템플릿 메서드 패턴 363 |
364 | 365 | * 상위 클래스의 템플릿 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴(행위 패턴) 366 | * 상속을 이용해서 동일한 코드를 제외하고 코드를 추가 367 | * 예시 368 | ```java 369 | public abstract class Animal { 370 | // 템플릿 메서드 371 | public void playWithOwner() { 372 | System.out.println("귀염둥이 이리온..."); 373 | play(); 374 | runSomething(); 375 | System.out.println("잘했어"); 376 | } 377 | 378 | // 추상 메서드 (오버라이딩 강제) 379 | abstract void play(); 380 | 381 | // 훅 메서드 (오버라이딩 선택) 382 | void runSomething() { 383 | System.out.println("꼬리 살랑 살랑~"); 384 | } 385 | } 386 | ``` 387 | ```java 388 | public class Dog extends Animal { 389 | 390 | @Override 391 | void play () { 392 | System.out.println("멍멍"); 393 | } 394 | 395 | @Override 396 | void runSomething() { 397 | System.out.println("멍멍 꼬리 살랑 살랑~"); 398 | } 399 | } 400 | ``` 401 | ```java 402 | public class Cat extends Animal { 403 | 404 | @Override 405 | void play () { 406 | System.out.println("야옹야옹"); 407 | } 408 | 409 | @Override 410 | void runSomething() { 411 | System.out.println("야옹야옹 꼬리 살랑 살랑~"); 412 | } 413 | } 414 | ``` 415 | 416 |
417 |
418 | 419 |
420 | 전략 패턴 421 |
422 | 423 | * 클라이언트가 전략을 생성해 전략을 실행한 컨텍스트에 주입하는 패턴(행위 패턴) 424 | * 객체 주입을 통해서 동일한 코드를 제외하고 코드를 추가 425 | * 전략 패턴 각 구성 요소 426 | * 전략 메서드를 가진 전략 객체 427 | * 전략 객체를 사용하는 컨텍스트 428 | * 전략 객체를 생성해 컨텍스트에 주입하는 클라이언트 429 | * 예시 430 | ```java 431 | public interface Strategy { 432 | public abstract void runStrategy(); 433 | } 434 | ``` 435 | ```java 436 | // 전략 객체 437 | public class StrategyGun implements Strategy { 438 | @Override 439 | public void runStrategy() { 440 | System.out.println("탕탕"); 441 | } 442 | } 443 | ``` 444 | ```java 445 | // 전략 객체 446 | public class StrategySword implements Strategy { 447 | @Override 448 | public void runStrategy() { 449 | System.out.println("챙챙"); 450 | } 451 | } 452 | ``` 453 | ```java 454 | // 컨텍스트 455 | public class Solider { 456 | void runContext(Strategy strategy) { 457 | System.out.println("전투 시작"); 458 | strategy.runStrategy(); 459 | System.out.println("전투 종료"); 460 | } 461 | } 462 | ``` 463 | ```java 464 | // 클라이언트 465 | public class Client { 466 | public static void main(String[] args) { 467 | Strategy strategy = null; 468 | Solider solider = new Solider(); 469 | 470 | // 총을 통한 전투 471 | strategy = new StrategyGun(); 472 | solider.runContext(strategy); 473 | 474 | // 검을 통한 전투 475 | strategy = new StrategySword(); 476 | solider.runContext(strategy); 477 | } 478 | } 479 | ``` 480 | 481 |
482 |
483 | 484 |
485 | 옵서버 패턴 486 |
487 | 488 | * 한 객체의 상태 변화를 관찰하다가 변화가 있을 때마다 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 패턴으로 일대다 객체 의존 관계를 구성하는 패턴(행위 패턴) 489 | * 예시 490 | ```java 491 | interface Subject { 492 | public void register(Observer obj); 493 | public void unregister(Observer obj); 494 | public void notifyObservers(); 495 | public Object getUpdate(Observer obj); 496 | } 497 | ``` 498 | ```java 499 | interface Observer { 500 | public void update(); 501 | } 502 | ``` 503 | ```java 504 | class Topic implements Subject { 505 | private List observers; 506 | private String message; 507 | 508 | public Topic() { 509 | this.observers = new ArrayList<>(); 510 | this.message = ""; 511 | } 512 | 513 | @Override 514 | public void register(Observer obj) { 515 | if (!observers.contains(obj)) observers.add(obj); 516 | } 517 | 518 | @Override 519 | public void unregister(Observer obj) { 520 | observers.remove(obj); 521 | } 522 | 523 | @Override 524 | public void notifyObservers() { 525 | this.observers.forEach(Observer::update); 526 | } 527 | 528 | @Override 529 | public Object getUpdate(Observer obj) { 530 | return this.message; 531 | } 532 | 533 | public void postMessage(String msg) { 534 | System.out.println("Message sended to Topic: " + msg); 535 | this.message = msg; 536 | notifyObservers(); 537 | } 538 | } 539 | ``` 540 | ```java 541 | class TopicSubscriber implements Observer { 542 | private String name; 543 | private Subject topic; 544 | 545 | public TopicSubscriber(String name, Subject topic) { 546 | this.name = name; 547 | this.topic = topic; 548 | } 549 | 550 | @Override 551 | public void update() { 552 | String msg = (String) topic.getUpdate(this); 553 | System.out.println(name + ":: got message >> " + msg); 554 | } 555 | } 556 | ``` 557 | ```java 558 | public class TestApplication { 559 | public static void main(String[] args) { 560 | 561 | Topic topic = new Topic(); 562 | Observer a = new TopicSubscriber("a", topic); 563 | Observer b = new TopicSubscriber("b", topic); 564 | Observer c = new TopicSubscriber("c", topic); 565 | 566 | topic.register(a); // 옵저버 등록 567 | topic.register(b); // 옵저버 등록 568 | topic.register(c); // 옵저버 등록 569 | 570 | topic.postMessage("amumu is op champion!!"); // 상태 변화 노티 571 | } 572 | } 573 | ``` 574 |
575 |
576 | 577 | 578 |
579 | MVC 패턴 580 |
581 | 582 | * Model, View, Controller라고 하는 컴포넌트로 분리하여 `비지니스 처리 로직`과 사용자 `인터페이스 요소`를 분리시켜 서로 영향없이 개발하기 수월 583 | 584 |
585 |
586 | -------------------------------------------------------------------------------- /Etc/README.md: -------------------------------------------------------------------------------- 1 | # 기타 2 | 3 |
4 | 5 | 6 |
7 | 함수형 프로그래밍 8 |
9 | 10 | * 부수 효과가 없는 순수함수로 프로그램을 만드는 것 11 | * 순수함수: 데이터 값을 변경시키지 않음, 객체의 필드를 설정하지 않음 12 | * 1급 객체와 데이터 불변성 그리고 고차함수, 합성함수, 순수함수와 같은 다양한 함수 개념으로 구성 13 | 14 | #### 참고 15 | * 명령형 프로그래밍: 무엇(What)보다는 `어떻게(How)`할 건지를 설명하는 방식 16 | * 절차지향 프로그래밍: 수행되어야 할 순차적인 처리 과정을 포함하는 방식 (C, C++) 17 | * 객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현 (C++, Java, C#) 18 | * 선언형 프로그래밍: 어떻게(How)보다는 `무엇(What)`을 할 건지를 설명하는 방식 19 | * 함수형 프로그래밍: 순수 함수를 조합해 소프트웨어를 만드는 방식 (클로저, 하스켈, 리스프) 20 | 21 |
22 |
23 | 24 | 25 |
26 | 포인터 27 |
28 | 29 | * 메모리 상의 주소를 저장하는 공간 30 | 31 |
32 |
33 | 34 | 35 |
36 | 얕은 복사와 깊은 복사 37 |
38 | 39 | #### 얕은 복사 40 | * `주소 값`을 복사 41 | * 참조하고 있는 실제 값은 같음 -> 복사한 객체의 값을 변경하면 기존 객체도 변경 42 | * 자바에서 객체는 Heap, 객체의 주소는 Stack에 저장 -> Stack에 Heap의 주소를 참조하는 공간이 1개 더 생성 43 | 44 | #### 깊은 복사 45 | * `실제 값`을 새로운 메모리 공간에 복사 46 | * 자바에서 객체는 Heap, 객체의 주소는 Stack에 저장 -> Heap에 객체가 1개 더 생성, Stack에 Heap의 주소를 참조하는 공간 생성 47 | 48 |
49 | 참고: 파이썬 50 |
51 | 52 | * 단순 객체 복사 53 | ```python 54 | # mutable 객체 (변경가능 객체(리스트 등)) 55 | a = [1, 2, 3, 4] 56 | b = a # copy 57 | print(b) # [1, 2, 3, 4] 58 | b[2] = 100 # b의 item 변경 59 | print(b) # [1, 2, 100, 4] 60 | print(a) # [1, 2, 100, 4], a의 item도 수정됨!! 61 | 62 | # immutable 객체 63 | a = 10 64 | b = a 65 | print(b) # 10 출력 66 | b = "abc" 67 | print(b) # abc 출력 68 | print(a) # 10 출력 69 | ``` 70 | 71 | * 얕은 복사 72 | * 객체를 복사할 때, 해당 객체만 복사하여 새 객체를 생성한다. 73 | * 복사된 객체의 인스턴스 변수는 원본 객체의 인스턴스 변수와 같은 메모리 주소를 참조한다. 74 | * 따라서, 해당 메모리 주소의 값이 변경되면 원본 객체 및 복사 객체의 인스턴스 변수 값은 같이 변경된다. 75 | ```python 76 | import copy 77 | 78 | # immutable 79 | a = [1, [1, 2, 3]] 80 | b = copy.copy(a) # shallow copy 발생 81 | print(b) # [1, [1, 2, 3]] 출력 82 | b[0] = 100 # 숫자 83 | print(b) # [100, [1, 2, 3]] 출력, 84 | print(a) # [1, [1, 2, 3]] 출력, shallow copy 가 발생해 복사된 리스트는 별도의 객체이므로 item을 수정하면 복사본만 수정된다. (immutable 객체의 경우 85 | 86 | # mutable 87 | c = copy.copy(a) 88 | c[1].append(4) # 리스트의 두번째 item(내부리스트)에 4를 추가 c[1]=[1,2,3,4] : list (mutable) 89 | print(c) # [1, [1, 2, 3, 4]] 출력 90 | print(a) # [1, [1, 2, 3, 4]] 출력, a가 c와 똑같이 수정된 이유는 리스트의 item 내부의 객체는 동일한 객체이므로 mutable한 리스트를 수정할때는 둘다 값이 변경됨 91 | ``` 92 | 93 | * 깊은 복사 94 | * 복사본의 값이 mutable한 객체일때, 이를 변경했을 시, 원본의 값도 변경되는 현상을 해결 95 | * 객체를 복사 할 때, 해당 객체와 인스턴스 변수까지 복사하는 방식 96 | * 전부를 복사하여 새 주소에 담기 때문에 참조를 공유하지 않는다. 97 | ```python 98 | import copy 99 | 100 | a = [1, [1, 2, 3]] 101 | b = copy.deepcopy(a) # deep copy 실행 102 | print(b) # [1, [1, 2, 3]] 출력 103 | b[0] = 100 # immutable 104 | b[1].append(4) # mutable 105 | print(b) # [100, [1, 2, 3, 4]] 출력 106 | print(a) # [1, [1, 2, 3]] 출력 107 | ``` 108 |
109 |
110 | 111 |
112 |
113 | 114 | 115 |
116 | TDD (Test Driven Development) 117 |
118 | 119 | * 테스트 주도 개발 120 | * `테스트 코드를 작성 한 후 그것을 통과하는 실행 코드를 작성`하는 매우 짧은 Cycle로 개발 121 | * 디버깅이 쉬워지고 코드의 신뢰성이 높아짐 122 | * 작성하는 코드의 길이가 길어지는 단점이 있음 123 | 124 |
125 |
126 | 127 | 128 |
129 | DDD (Domain Driven Design) 130 |
131 | 132 | * 도메인 중심 설계 방법, 도메인이 상호작용 하도록 설계하는 것 133 | * 도메인은 각각 분리되어 있어 MSA에 용이한 설계 가능 134 | * 문맥에 따라 객체의 역할이 바뀔 수 있음: 같은 객체가 존재할 수 있음 135 | * 예) 구매 도메인, 판매 도메인 136 | 137 |
138 |
139 | 140 | 141 |
142 | 크롬 탭은 프로세스인지 스레드인지 143 |
144 | 145 | * 크롬은 탭마다 PID를 가지고 있는 Process 146 | * 각 Tab마다 랜더링 정보나 기타 데이터를 따로 관리, 그로 인해 메모리를 많이 잡아먹기도 하지만 하나의 Tab에 오류가 생겼다고 모든 Tab에 영향을 끼치진 않는 장점이 존재 147 | 148 |
149 |
150 | 151 | 152 |
153 | 프레임워크와 라이브러리의 차이 154 |
155 | 156 | * 실행 흐름을 제어하는 권한이 어디에 있는 가의 차이 157 | 158 | #### 프레임워크 159 | * 흐름을 자체적으로 제어 160 | * IoC가 적용되는 것 161 | 162 | #### 라이브러리 163 | * 흐름 제어가 필요할 때, 사용자가 필요한 상황에 가져다 쓸 수 있는 것 164 | 165 | 166 |
167 |
168 | 169 | 170 | 171 |
172 | Git에서 merge와 rebase의 차이 173 |
174 | 175 | * git merge를 하면 브랜치의 커밋 로그는 사라지고 `병합하는 커밋 로그가 master에 head에 추가` 176 | * git rebase를 하면 브랜치를 base로 master `커밋을 재정렬하여 브랜치의 커밋 하나 하나가 master에 정리되어 추가` 177 | 178 |
179 |
180 | 181 | 182 |
183 | 메시지 큐 (Message Queue) 184 |
185 | 186 | * Queue 자료구조를 이용해 데이터(메시지)를 관리하는 시스템 187 | * 비동기 통신으로 메시지를 빠르게 교환 188 | * Producer가 메시지를 큐에 넣으면 Consumer가 메시지를 가져와 처리 189 | * 예) Kafka, Rabbit MQ, AMPQ 190 | 191 |
192 |
193 | -------------------------------------------------------------------------------- /Java/README.md: -------------------------------------------------------------------------------- 1 | # Java 2 | 3 |
4 | 5 |
6 | Java 특징 7 |
8 | 9 | * 미국의 Sun마이크로시스템이 개발 10 | * `객체 지향` 프로그래밍 언어, `컴파일` 언어 11 | * JVM만 있으면 OS와 상관없이 동작 가능(운영체제에 독립적) 12 | * 고성능(High Performance): 바이트 코드로 변환되어 실행 13 | * 멀티 스레딩 지원 14 | 15 |
16 |
17 | 18 | 19 |
20 | JVM(Java Virtual Machine) 21 |
22 | 23 | * `자바 프로그램을 실행`하는 역할 24 | * 컴파일러를 통해 바이트 코드로 변환된 파일을 JVM에 로딩하여 실행 25 | * Garbage Collection 수행 (메모리 관리) 26 | * `Class Loader`: JVM 내(Runtime Data Area)로 Class 파일을 로드하고 링크 27 | * `Excution Engine`: 메모리(Runtime Data Area)에 적재된 클래스들을 기계어로 변경해 실행 28 | * 인터프리터: 바이트 코드를 한줄씩 읽어 기계어로 변환 29 | * JIT 컴파일러: 반복되는 코드를 기계어로 변환해 캐싱 (-> 캐싱한 것을 바로 실행해 속도 향상) 30 | * `Garbage Collecter`: 힙 메모리에서 참조되지 않는 객체를 제거 31 | * `Runtime Data Area`: 자바 프로그램을 실행할 때, OS로부터 할당받는 `메모리` 32 | 33 |
34 |
35 | 36 | 37 |
38 | Java 프로그램 실행 과정 39 |
40 | 41 | * JVM은 OS로부터 메모리(Runtime Data Area)를 할당받음 42 | * `컴파일러(javac)`가 `소스코드(.java)`를 읽어들여 `바이트 코드(.class)`로 변환 43 | * `Class Loader`를 통해 Class 파일을 `JVM 내의 Runtime Data Area에 로딩` 44 | * 로딩된 Class 파일을 `Excution Engine을 사용해 해석 및 실행` 45 | 46 |
47 |
48 | 49 | 50 |
51 | JVM 메모리(Runtime Data Area) 구조 52 |
53 | 54 | #### JVM 구조 55 | 56 | * 크게 `메소드 영역, JVM 스택, JVM 힙`으로 나뉘며 JVM 힙은 `Young Generation, Old Generation`으로 나뉘고 Young Generation은 `Eden, Survivor0, Survivor1`으로 나뉨 57 | 58 | #### Method Area 59 | * 모든 스레드가 공유 60 | * Class Loader가 적재한 `클래스/인터페이스에 대한 정보(바이트 코드)`를 저장 61 | * 이 영역에 등록된 클래스만 Heap에 생성 가능 62 | * 타입 정보(클래스 or 인터페이스, 접근 제어자 등), 메소드(생성자 포함, 이름, 리턴 타입, 접근 제어자 등), 필드(데이터 타입, 접근 제어자), Static(클래스) 변수 63 | * Runtime Comstant Pool: 클래스와 인터페이스/메소드/필드에 대한 모든 레퍼런스 저장 64 | * JVM은 이를 이용해 실제 메모리 주소를 찾아 참조 65 | 66 | #### JVM 힙 67 | * 모든 스레드가 공유 68 | * `런타임`에 `동적`으로 할당하여 사용하는 영역 69 | * new 연산자로 생성된 객체 저장 70 | * `GC`의 대상: 힙 영역의 객체는 스택의 변수나 다른 객체에서 참조, 참조가 없으면 GC 대상 71 | 72 | #### JVM 스택 73 | * 스레드마다 존재, 스레드가 시작될 때 할당, LIFO 74 | * 지역변수, 매개변수, 연산 중 발생하는 임시 데이터 저장 75 | * 참고 76 | * `기본 타입` 변수: 스택에 `값` 저장 77 | * `참조 타입` 변수: 힙이나 메소드 영역 객체의 `주소` 저장 78 | 79 | #### Native Method Stack 80 | * 스레드마다 존재 81 | * 자바가 아닌 언어로 작성된 네이티브 코드를 위한 스택 82 | 83 | #### PC 레지스터 84 | * 스레드마다 존재 85 | * 현재 수행 중인 JVM 명령어의 주소를 가짐 86 | 87 |
88 |
89 | 90 | 91 |
92 | 변수의 종류와 메모리 구조 93 |
94 | 95 | * 인스턴스 변수: 객체에서 사용되는 변수 -> 힙 영역 96 | * 클래스 변수: static 변수 -> 메소드 영역 97 | * 지역 변수: 메소드 내에서 선언되어 메소드 안에서만 사용할 수 있는 변수 -> 스택 영역 98 | 99 | ```java 100 | public class Test{ 101 | private int iv; // 인스턴스 변수 102 | public static int cv; // 클래스 변수 103 | public void print(){ 104 | int lv; // 지역 변수 105 | } 106 | } 107 | ``` 108 | 109 |
110 |
111 | 112 | 113 |
114 | Java에서 Garbage Collection이 필요한 이유 115 |
116 | 117 | * Garbage: 더 이상 사용되지 않는 메모리, 객체를 가리키는 레퍼런스가 없는 것 118 | * 자바는 메모리를 명시적으로 해제하지 않기 때문에 GC를 통해서 필요없는 객체를 지움 119 | * 더이상 사용하지 않는 `동적 할당된 메모리 블럭(Heap)`을 찾아 다시 사용 가능한 자원으로 회수 120 | 121 |
122 |
123 | 124 | 125 |
126 | Garbage Collection 동작 방식 127 |
128 | 129 | #### GC 130 | 131 | * 새롭게 생성된 객체는 `Heap`의 `Young Generation의 Eden 영역`에 저장 132 | * `Eden 영역이 다 차면 Minor GC`가 발생하여 참조 횟수에 따라 증가하는 `age bit`를 보고 불필요한 객체를 삭제하고 생존한 객체는 `S0`으로 이동 133 | * Minor GC가 발생할 때마다 Young 영역의 객체들은 삭제와 이동을 함 (Eden -> S0 / S0 -> S1 / S0 <- S1) 134 | * S1이 가득 차면 필요한 객체는 `OLD 영역으로 이동(Promition)`하고 `OLD 영역이 가득차면 Major GC`를 통해서 값을 삭제 135 | 136 | #### 참고 137 | * age bit: 각 객체가 Minor GC에서 살아남은 횟수를 기록, Minor GC가 발생할 때마다 하나씩 증가, age bit 값이 MaxTenuringThreshold 라는 설정 값을 초과하면 Old Generation으로 객체가 이동 138 | * STOP THE WORLD: GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춤, GC 작업을 완료한 이후에야 중단했던 작업을 다시 시작 139 | * GC가 실행될 때마다 `STOP THE WORLD`가 발생하여 프로그램이 중지 140 | 141 | #### 참고: Heap 142 | ##### Young Generation 143 | * 자바의 객체가 생성되자마자 저장, 생성된지 오래되지 않은 객체가 저장 144 | * 시간이 지나 우선순위가 낮아지면(Young에서 오랫동안 사용되면) Old Generation으로 이동 145 | * `Minor GC` 발생 146 | * `Eden`, `Survivor0`, `Survivor1`로 구성 147 | 148 | ##### Old Generation 149 | * Young Generation에서 옮겨진 객체를 저장 150 | * 객체가 사라질 때, `Major GC` 발생 151 | 152 | ##### (Non-Heap) Permanent Generation 153 | * Java7버전까지는 Heap에 존재, 8부터는 Native Method Stack에 Meta Space로 변경 154 | * Class Loader에 의해 Load된 클래스의 메타 데이터 저장 155 | 156 |
157 |
158 | 159 | 160 |
161 | 추상 클래스와 인터페이스 162 |
163 | 164 | #### 추상 클래스 165 | * 반드시 `구현(오버라이딩)`해야하는 추상 메소드를 1개 이상 갖고 있는 클래스 166 | * 실체 클래스의 공통적인 변수와 메소드를 추출해 선언한 클래스 167 | * 추상 메소드와 클래스 모두에 `abstract` 키워드를 붙여서 표기, 추상 클래스의 상속에는 `extends` 키워드 사용 168 | * 추상 클래스와 실체 클래스는 `상속관계` -> 실체 클래스는 추상 클래스의 추상 메소드를 상속받아 `오버라이딩` 해야 함 169 | * 사용 이유 170 | * 필드와 메소드 통일: 유지보수성 향상 및 통일성 유지 (A객체를 B객체로 변경할 경우 -> 필드/메서드가 동일하면 객체만 변경하면 됨) 171 | * 규격에 맞는 실체 클래스 구현: 추상클래스의 추상 메소드는 반드시 오버라이딩되어야 함 172 | * 일반적인 추상화 및 상속에 더 초점, `상속 받아서 기능을 확장`시키는데 목적 173 | 174 | ```java 175 | public abstract class AbstractClass { 176 | public void function() {}; 177 | public abstract void abstractFunction(); 178 | } 179 | ``` 180 | 181 | #### 인터페이스 182 | * 어떤 메소드를 제공하는지 알려주는 명세(Specification) 183 | * 추상 클래스의 일종으로 default 메소드와 static 메소드를 제외하면 `추상 메소드와 상수만` 가짐 184 | * 상속 관계가 없는 클래스에서 공통되는 로직을 구현하여 사용 185 | * `interface` 키워드를 통해 선언, `implements`로 일반 클래스에서 인터페이스를 구현 186 | * 사용 이유 187 | * 동일한 목적 하에 동일한 기능을 보장하는 것 -> 메서드를 구현하게 하는 것에 초점 188 | * 다형성 극대화 -> 코드의 수정은 감소, 유지보수성 증가 189 | 190 | ```java 191 | public interface Interface { 192 | public int max = 10; // 상수, 무조건 인터페이스에서 제공하는 값을 사용 193 | public abstract void abstractFunction(); // 추상 메소드: 일반 클래스에서 오버리이딩 필수 194 | default void function(){} // default 메소드: 인터페이스에서 제공하는 것을 사용하거나 일반 클래스에서 따로 구현하여 사용할 수 있음 195 | // 추가 요건으로 메소드를 추가할 때, default를 사용하면 유지보수성을 높일 수 있음 196 | // 추상 메소드를 추가하면 일반 클래스에서 이를 구현하지 않으면 모두 에러가 발생하기 때문 197 | static void function2(){} // 정적 메소드: 무조건 인터페이스에서 제공하는 것을 사용 198 | } 199 | ``` 200 | 201 | #### 공통점 202 | * 두 가지 개념 모두 독립적으로 객체 생성 불가, 상속을 목적으로 사용 203 | * 추상 메소드는 오버라이딩이 필요 204 | 205 | #### 차이점 206 | * 추상 클래스는 다중 상속 불가능, 인터페이스는 다중 상속 가능 207 | * 추상 클래스는 상속을 통해 기능을 확장하는 것이 목적 208 | * 인터페이스는 추상 클래스와 달리 구현을 강제함으로써 `구현 객체의 같은 동작`을 보장하여 인터페이스를 이용하여 `표준화를 확립할 수 있으므로 서로 관계가 없는 객체들이 상호 작용을 가능하게 함` 209 | 210 | #### 참고 211 | * https://wildeveloperetrain.tistory.com/112 212 | 213 |
214 |
215 | 216 |
217 | Collection Framework 218 |
219 | 220 | #### JAVA Collection 221 | * 데이터를 효율적으로 관리할 수 있는 자료구조와 알고리즘을 구조화하여 클래스로 구현한 것 222 | * `List, Set, Map 인터페이스`가 존재 223 | * Collection Interface -> List, Set 224 | * Map Interface 225 | 226 | #### List 227 | * 순서가 있는 데이터 집합, 데이터의 중복 허용 228 | * `ArrayList`(`Vector`를 개선), `Vector`, `Stack`, `LinkedList` 229 | * Stack과 Queue: Stack은 직접 new 키워드로 사용할 수 있으며, Queue는 LinkedList에 new 키워드를 적용하여 사용 230 | 231 | #### Set 232 | * 데이터의 중복을 허용하지 않음 233 | * `Hash Set`: value에 대해서 중복된 값을 저장하지 않음 234 | 235 | #### Map 236 | * 키와 값의 쌍으로 이루어진 데이터 집합 237 | * 키는 중복을 허용하지 않고 값의 중복은 허용 238 | * `Hash Map`: 해시테이블처럼 `key-value`의 구조로 이루어져 있으며 key를 기준으로 중복된 값을 저장하지 않으며 순서를 보장하지 않음 239 | 240 |
241 |
242 | 243 | 244 |
245 | Vector와 ArrayList 차이 246 |
247 | 248 | * Vector: Thread-Safe 249 | * ArrayList: Thread-SafeX 250 | 251 |
252 |
253 | 254 | 255 |
256 | Hash Map과 Hash Table의 차이 257 |
258 | 259 | * Hash Map: 메소드 동기화X, Thread Safe 아님, 성능 빠름 260 | * Hash Table: 메소드 동기화 지원, Thread Safe, 성능 느림 261 | 262 |
263 |
264 | 265 | 266 |
267 | Hash Map과 Tree Map의 차이 268 |
269 | 270 | * Hash Map: 해싱 구현, 랜덤 정렬(순서 유지X), Null 키 가능, 훨씬 빠름 271 | * Tree Map: 레드블랙트리(이진탐색트리)로 구현, key로 자동 정렬, Null 키 불가능 272 | 273 |
274 |
275 | 276 | 277 |
278 | Hash Set과 Tree Set의 차이 279 |
280 | 281 | * Hash Set: 해싱으로 구현, 삽입된 요소는 랜덤 정렬, Null 저장 가능, 성능 빠름, 값 비교에 equals 사용 282 | * Tree Set: 레드블랙트리(이진탐색트리) 구현, 정렬 순서 유지(자동 정렬), Null 저장 불가, 성능 느림, 값 비교에 comparedTo 사용 283 | 284 |
285 |
286 | 287 | 288 |
289 | Generic 290 |
291 | 292 | * `컴파일 과정에서 타입을 체크`하는 기능 293 | * 클래스 내부에서 사용할 데이터 `타입`을 외부에서 지정하는 기법 294 | * 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에서 사용 295 | * 사용 이유 296 | * 잘못된 타입이 사용될 문제를 컴파일 과정에서 제거 가능 297 | * 코드 재사용성 증가 298 | 299 |
300 |
301 | 302 | 303 |
304 | Annotation 305 |
306 | 307 | * 어노테이션이란 본래 주석이란 뜻이지만, 자바에서는 인터페이스를 기반으로 한 문법 308 | * `코드에 달아 클래스에 특별한 의미를 부여하거나 기능을 주입함` 309 | 310 |
311 |
312 | 313 | 314 |
315 | Access Modifier(접근 제한자) 316 |
317 | 318 | * public: 모든 클래스에서 접근할 수 있다는 것을 의미(패키지가 달라도 허용) 319 | * protected: `같은 패키지`에서 접근 허용, `다른 패키지의 상속`받은 클래스에서 접근 허용, 다른 패키지의 다른 클래스에서 접근 불가 320 | * default: `같은 패키지` 내에서만 접근 허용 321 | * private: 동일 패키지라도 접근 불가, `같은 클래스` 내에서만 접근 허용 322 | * 사용 이유 323 | * 정보은닉(민감 정보 유출 안하기), 외부에서 알 필요 없는 값은 노출X 324 | * 응집도 높이고 결합도 낮추기 325 | 326 |
327 |
328 | 329 | 330 |
331 | final 키워드 332 |
333 | 334 | * final 키워드는 `상수`로 정의하는 키워드 335 | * final class: 다른 클래스에서 상속하지 못함 336 | * final method: 다른 메소드에서 오버라이딩하지 못함 (오버로딩 가능) 337 | * final variable: 변하지 않는 상수값이 되어 새로 할당할 수 없는 변수가 됨 338 | * 생성자: final이 될 수 없음 339 | 340 |
341 |
342 | 343 | 344 |
345 | non-static과 static 멤버의 차이 346 |
347 | 348 | #### non-static 349 | * 객체마다 멤버가 존재 350 | * 객체 생성 시에 멤버 생성 351 | * 객체가 생성될 때 멤버 생성, 객체가 사라질 때 멤버가 사라짐 352 | * 같은 클래스의 객체 사이에서 공유되지 않음 353 | 354 | #### static 355 | * 객체를 많이 생성해도 해당 변수는 한개만 존재(객체와 무관한 키워드), 클래스당 1개 존재 356 | * 클래스를 로딩할 때, 멤버 생성, 처음 설정된 메모리 공간이 변하지 않음을 의미 357 | * 객체가 생성되기 전에 사용 가능, 객체가 사라져도 멤버 사라지지 않음 -> 프로그램 종료 시 사라짐 358 | * 동일한 클래스의 모든 객체들에 의해 공유 359 | 360 |
361 |
362 | 363 | 364 |
365 | Wrapper Class 366 |
367 | 368 | * 기본 타입 데이터를 객체로 포장해주는 클래스 369 | * 기본 타입 데이터를 객체로 만들어야 할 경우 사용 370 | * Byte, Integer, Long, Double, Boolean, Character 등 371 | 372 | #### Boxing 373 | * 기본 타입 -> 래퍼 클래스 374 | 375 | ```java 376 | Integer num = new Integer(17); 377 | ``` 378 | 379 | #### Unboxing 380 | * 래퍼 클래스 -> 기본 타입 381 | 382 | ```java 383 | int n = num.intValue(); 384 | ``` 385 | 386 |
387 |
388 | 389 | 390 |
391 | 기본(원시)형과 참조형의 차이점 392 |
393 | 394 | * 기본형: boolean, char, byte, short, int, long, float, double 395 | * 참조형: 기본형 8가지를 제외한 나머지 타입, Integer, Long, Double, Boolean 등 396 | * 참조형은 null을 입력할 수 있지만 기본형은 null 불가능 397 | 398 | ```java 399 | int i = null; //불가능 400 | Integer ii = null; //가능 401 | ``` 402 | 403 | * 참조형은 제너릭 타입에서 사용 가능하지만 기본형은 불가능 404 | * 제너릭(Generic): 클래스에서 사용할 타입을 클래스 외부에서 설정, 타입을 파라미터화해서 컴파일시 구체적인 타입이 결정 405 | 406 | ```java 407 | List i; //불가능 408 | List ii; //가능 409 | ``` 410 | 411 | * 참조형은 할당연산자 사용 시에 값의 주소가 전달되고 기본형은 값 자체가 전달 -> 기본형은 `스택`에 값이 존재, 참조형은 값은 `힙`에 존재하고 `스택`에 참조 값이 존재해 언박싱 필요 412 | * 참조형은 기본형보다 차지하는 메모리가 크고 접근 속도가 느림 413 | 414 |
415 |
416 | 417 | 418 |
419 | Integer와 int 420 |
421 | 422 | #### Integer 423 | * Wrapper Class로 Unboxing을 해야 산술 연산이 가능하고 null을 처리할 수 있음 424 | * int를 클래스로 감싼 형태 425 | 426 | #### int 427 | * 기본 자료형으로 산술 연산이 가능하고 null 처리는 불가능 428 | 429 |
430 |
431 | 432 | 433 |
434 | int와 short 435 |
436 | 437 | #### int 438 | * 4바이트 439 | 440 | #### short 441 | * 2바이트 442 | 443 |
444 |
445 | 446 | 447 |
448 | String, StringBuilder, StringBuffer 449 |
450 | 451 | #### String, StringBuilder, StringBuffer 특성 452 | 453 | * String: `불변성`, StringBuilder/StringBuffer: `가변성` 454 | 455 | #### String 456 | * 값을 변화시킬 때, Heap에 새로운 메모리를 사용, 스택에서 참조되는 메모리 주소 변경 457 | * 기존 Heap 메모리는 GC의 대상이 됨 458 | * 값이 바뀌지 않는 문자열에 사용하는 것이 좋음 459 | * 단순 읽기에서 성능 좋음 460 | * Thread-Safe: 동기화 지원 461 | 462 | #### StringBuilder 463 | * 같은 객체에서 값을 바꿀수 있음 464 | * Thread-Safe 아님: 동기화 지원하지 않음 465 | * StringBuffer보다 빠름 466 | 467 | #### StringBuffer 468 | * 같은 객체에서 값을 바꿀수 있음 469 | * Thread-Safe: 동기화 지원 470 | 471 |
472 |
473 | 474 | 475 |
476 | ==와 equals()의 차이 477 |
478 | 479 | * == 연산자는 참조형을 비교할 때 `레퍼런스(주소)를 비교`하고 eqals()는 참조형을 비교할 때 `값을 비교` 480 | 481 | ```java 482 | String a = "string"; // 리터럴 선언: String Constant Pool (힙) 483 | String b = "string"; 484 | String c = new String("string"); // new 선언: 힙 485 | 486 | System.out.println(a == b); // true // 주소 비교인데 같은 객체를 가리킴 487 | System.out.println(a == c); // false 488 | 489 | System.out.println(a.equals(b)); // true 490 | System.out.println(a.equals(c)); // true 491 | ``` 492 | 493 |
494 |
495 | 496 | 497 |
498 | 람다 표현식 499 |
500 | 501 | * `익명 함수`(Anonymous Function)의 한 종류 502 | * 함수를 따로 만들지 않고 코드 한 줄에 함수를 써서 그것을 호출 503 | * 자바8부터 지원, 코드가 간결하고 가독성이 높음 504 | * 재사용이 불가능하고 디버깅이 어려움 505 | * 예시: Optional, Stream 506 | 507 |
508 |
509 | 510 | 511 |
512 | Thread 생성방법 513 |
514 | 515 | * `Thread 클래스 상속` 516 | * `Runnable 인터페이스 구현` 517 | 518 |
519 |
520 | 521 | 522 |
523 | Synchronized 524 |
525 | 526 | * 공유 자원에 두개 이상의 쓰레드가 동시에 접근하지 못하도록 `Lock` 527 | * 자바에서는 메소드 앞에 `synchronized`를 붙여 동기화 528 | * 객체에도 사용 가능 529 | 530 |
531 |
532 | 533 | 534 |
535 | ThreadLocal 536 |
537 | 538 | * 오직 한 쓰레드에 의해 읽고 쓰여질 수 있는 변수를 생성 539 | * 다른 쓰레드가 같은 ThreadLocal을 호출해도 서로 다른 값을 가짐 540 | 541 |
542 |
543 | 544 | 545 |
546 | Casting 547 |
548 | 549 | #### 업캐스팅 550 | * 자식 클래스의 객체가 부모 클래스의 객체로 캐스팅 551 | 552 | ```java 553 | SuperClass super = new ChildClass(); 554 | super.childFunction(); // 자식 클래스의 함수 실행 555 | ``` 556 | 557 | * 부모 클래스의 함수를 오버라이딩한 자식 클래스의 함수 실행 가능 558 | * 부모 클래스의 static 메소드 실행 가능 559 | * 자식 클래스에만 있는 멤버는 실행 불가(컴파일 에러) 560 | 561 | #### 다운캐스팅 562 | * 부모 클래스의 객체가 자식 클래스로 캐스팅 -> 업캐스팅되어 고유의 특성을 잃은 자식 클래스의 객체를 복구시키는 것 563 | 564 | ```java 565 | SuperClass super = new ChildClass(); 566 | ChildClass child = (ChildClass)super; 567 | child.superFunction(); //가능 568 | ``` 569 | 570 |
571 |
572 | 573 | 574 |
575 | Promotion과 Casting 576 |
577 | 578 | #### Promotion: 묵시적 형변환 579 | * 작은 타입이 큰 타입으로 변환 580 | 581 | ```java 582 | int a = 10; float b; 583 | b = a; 584 | 585 | SuperClass super = new SubClass(); 586 | ``` 587 | 588 | #### Casting: 명시적 형변환 589 | * 큰 타입을 작은 타입으로 변환 590 | 591 | ```java 592 | int a; float b = 1.1; 593 | a = (int)b; 594 | 595 | SuperClass super; 596 | SubClass sub = (SubClass)super; 597 | ``` 598 | 599 |
600 |
601 | 602 | 603 |
604 | reflection 605 |
606 | 607 | * 런타임에 클래스를 사용해야 할 때 필요 608 | * 동적으로 객체를 생성하고 메서드를 호출하는 방법 609 | * Class, Constructor, Method, Field : 객체 생성, 메서드 호출, 변수 값 변경 등 가능 610 | 611 |
612 |
613 | 614 |
615 | Error와 Exception 616 |
617 | 618 | #### Error 619 | * `런타임`에서 실행 시 발생되며 모두 예측 불가능한 Unchecked Error 620 | * 핸들링 불가능 621 | 622 | #### Exception 623 | * Checked Exception: 실행하기 전에 예측 가능 -> SQLException, FileNotFoundException 624 | * Unchecked Exception: 실행하고 난 후에 알 수 있음 -> ArrayIndexOutOfBoundException, NullPointerException(Null인 객체에 접근하면 발생) 625 | * 핸들링 가능, 예외 처리 가능(try ~ catch) 626 | 627 |
628 |
629 | 630 | 631 |
632 | Java7에서 Java8로 올라오면서 달라진 점 633 |
634 | 635 | * 람다 표현식 추가: 함수형 프로그래밍 636 | * Permanent Generation: Java7버전까지는 Heap에 존재, 8부터는 Native Method Stack에 Meta Space로 변경 637 | * 인터페이스에 default 메소드, static 메소드 추가 638 | * stream API: 데이터의 추상화 639 | * java.time 패키지: Joda-Time을 이용한 새로운 날짜와 시간 API 640 | 641 |
642 |
643 | 644 |
645 | Call by Value vs Call by Reference 646 |
647 | 648 | * `값을 복사`를 하여 처리하는지 `직접 참조`하는지의 차이 649 | * Call by Value: 인자로 받은 값을 복사하여 처리 650 | * Call by Reference: 인자로 받은 값의 주소를 참조하여 직접 값에 영향을 줌 651 | * JAVA에서는 모든 전달 방식이 Call by value로 Call by reference는 해당 객체의 주소값을 직접 넘기는 게 아닌 객체를 보는 또 다른 주소값을 만들어서 넘김 652 | 653 |
654 |
655 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yoonje Choi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LiveCoding/README.md: -------------------------------------------------------------------------------- 1 | # Live Coding 2 | 3 | * (트리 형태의 숫자를 주고) 주어진 모양의 트리를 정의하고 DFS 알고리즘을 구현하라. 4 | * (1이상 100이하 숫자 N개가 주어 지고) 이 N개의 수의 최소 공배수를 구하라. 5 | * 주어진 문자열이 반대로 뒤집어도 같은 글자인지 찾는 알고리즘을 구현하라. 6 | * 숫자가 들어있는 배열이 있을 때, 중복되는 숫자가 있는지 찾는 알고리즘을 구현하라. 7 | * Factorial을 구하는 함수를 재귀로 짜보세요. 8 | * 대각선이 고정인 행렬인 pivotal 3x3, 4x4를 뒤집는 로직을 재귀로 짜보세요. 9 | * atoi 함수를 구현하세요. 10 | * String으로 있는 출근 시간/퇴근 시간의 나열에서 내림차순으로 정렬하는 함수를 구현하세요. 11 | * 10진수로 입력받은 수를 입력받은 진수로 변환하는 함수를 구현하세요. 12 | * Binary Search(이진 탐색)를 구현해보세요. -------------------------------------------------------------------------------- /Network/README.md: -------------------------------------------------------------------------------- 1 | # Network 2 | 3 |
4 | 5 |
6 | OSI 7계층와 TCP/IP 4계층 7 |
8 | 9 | ![image](https://user-images.githubusercontent.com/38535571/230088639-3eeec45b-5ad5-48e6-8217-0e076cde69b0.png) 10 | 11 | #### OSI 7계층 12 | * 네트워크의 통신 과정을 7단계로 나눠 표준화한 것 13 | * ISO(국제표준기구)에서 만듦 14 | 15 | #### OSI Application(7, Message or Data) 16 | * 사용자에게 `실제 애플리케이션 서비스를 제공`하는 계층 17 | * HTTP, FTP, DNS 18 | #### OSI Presentation(6, Message or Data) 19 | * 애플리케이션의 `데이터 형태와 구조를 변환(번역, 암호화, 압축)`시키는 계층 20 | * 코드 간의 번역을 담당 -> 사용자 시스템에서 데이터의 형식상 차이를 다루는 부담을 응용 계층으로부터 덜어줌 21 | #### OSI Session(5, Message or Data) 22 | * 양 끝단의 응용 프로세스가 `통신을 관리하기 위한 방법`을 제공 23 | * 동시 송수신 방식(duplex)- 반이중 방식(half-duplex), 전이중 방식(Full Duplex)의 통신 등 24 | * 애플리케이션 간의 `TCP/IP 세션을 구축하고 관리하며 종료`시키는 계층 25 | * Socket 26 | #### OSI Transport(4, Segment) 27 | * 통신 `양단 간의 신뢰성 있는 통신`을 보장하는 계층 28 | * TCP, UDP 29 | #### OSI Network(3, Packet) 30 | * 목적지까지의 경로를 선택하고 `경로에 따라 패킷을 전달(라우팅)`해주는 계층 31 | * IP / 라우터 32 | #### OSI Link(2, Frame) 33 | * 인접한 `피어 간의 신뢰성 있는 통신`을 보장하는 계층 34 | * ARP, MAC / 브릿지, 스위치 35 | #### OSI Physical(1, Bit) 36 | * 전기적, 기계적, 기능적인 특성을 이용해서 `통신 케이블로 데이터를 전송` 37 | * 리피터, 케이블, 허브, NIC 38 | 39 | #### TCP/IP 4계층 40 | * 네트워크 통신 과정을 4계층으로 나눠 표현한 것 41 | * TCP/IP 4계층에서 에플리케이션 계층을 3개로 쪼개고 인터넷 계층을 네트워크 계층이라고 부르면서 링크 계층을 데이터 링크 계층과 물리 계층으로 나누면 OSI 7계층이 됨 42 | 43 | #### TCP/IP Application(4, Message) 44 | * 응용 프로그램이 사용되는 프로토콜 계층 45 | * HTTP, FTP, DNS 46 | #### TCP/IP Transport(3, Segment) 47 | * 송신자와 수신자를 연결하는 통신 서비스를 제공하며 애플리케이션과 인터넷 계층 사이의 데이터가 전달될 때 중계하는 역할을 하는 계층 48 | * TCP, UDP 49 | #### TCP/IP Internet(2, Packet) 50 | * 장치로부터 받은 네트워크 패킷을 IP 주소로 지정된 목적지로 전송하기 위해 사용되는 계층 51 | * IP 52 | #### TCP/IP Link(1,Frame/Bit) 53 | * 전선, 광섬유, 무선 등 실질적으로 데이터를 전달하며 장치 간에 신호를 주고 받는 규칙을 정하는 계층 54 | 55 |
56 |
57 | 58 | 59 |
60 | PDU 61 |
62 | 63 | #### PDU 64 | ![image](https://user-images.githubusercontent.com/38535571/230087342-ff3182cc-c6e1-485b-aeb2-71fd91e492cc.png) 65 | * 네트워크 어떠한 계층에서 다른 계층으로 데이터가 전달될 때 한 덩이리의 단위를 PDU(Protocal Data Unit)이라고 함 66 | * PDU는 메타 정보를 갖고 있는 `헤더`와 데이터를 의미하는 `페이로드`로 구성되며 계층마다 부르는 명칭이 다름 67 | 68 | #### 캡슐화와 비캡슐화 69 | ![image](https://user-images.githubusercontent.com/38535571/230087480-27c5292e-8066-4dae-aaf4-a21dd47ca4f9.png) 70 | * 캡슐화 과정은 상위 계층의 헤더와 데이터를 하위 계층의 데이터 부분에 포함시키고 해당 계층의 헤더를 삽입하는 과정 71 | * 비캡슐화 과정은 하위 계층에서 상위 계층으로 가며 각 계층의 헤더 부분을 제거하는 과정 72 | * 송신자의 애플리케이션 계층에서부터 각 계층에서 캡슐화를 통해 데이터가 생성되고 수신자의 링크 계층에서부터 각 계층에서 비캡슐화를 통해 데이터가 전달 73 | 74 |
75 |
76 | 77 |
78 | TCP와 UDP 79 |
80 | 81 | #### TCP 82 | * `신뢰성을 보장하는 연결형 프로토콜` 83 | * `흐름제어, 혼잡제어`를 제공 84 | * 웹 HTTP 통신, 이메일, 파일 전송에서 사용 85 | 86 | #### UDP 87 | * `신뢰성을 보장하지 않는 비연결형 프로토콜` 88 | * 흐름제어, 혼잡제어를 제공하지 않음 89 | * 속도가 중요한 서비스(스트리밍)에서 사용 90 | * UDP 자체는 신뢰성을 보장하지 않지만 추가적인 정의를 통해 보장 가능 (HTTP/3에서 QUIC 프로토콜) 91 | 92 |
93 |
94 | 95 |
96 | TCP 흐름제어 97 |
98 | 99 | #### TCP 흐름제어 100 | * `수신자와 송신자`의 메시지 처리속도 차이를 해결하기 위한 방법 101 | * 수신자는 윈도우 크기를 자신의 응답 헤더에 담아서 송신 측에게 전해주게 되고, 송신자는 상대방에게 데이터를 보낼 때 이 윈도우 크기를 확인 102 | 103 | #### 종류 104 | ##### Stop and Wait 105 | ![image](https://user-images.githubusercontent.com/38535571/230088843-64d1d387-0105-42a6-be71-5313a904db4d.png) 106 | * 전송한 패킷의 ACK을 수신하면 다음 패킷 전송 107 | 108 | ##### Sliding Window - Go Back N 109 | ![image](https://user-images.githubusercontent.com/38535571/230088958-430d6c0c-ccd1-44a1-b06a-e9e3f7191572.png) 110 | 111 | * 수신 측에서 설정한 윈도우 크기만큼의 패킷을 ACK의 확인 없이 전송, 데이터의 흐름을 동적으로 조절하는데 Cumulative ACK(마지막으로 수신 성공한 패킷의 ACK을 계속 전송)을 받고 문제가 된 패킷부터는 모두 재전송 112 | 113 | ##### Sliding Window - Selective Repeat 114 | * 수신 측에서 설정한 윈도우 크기만큼의 패킷을 ACK의 확인 없이 전송, 데이터의 흐름을 동적으로 조절하는데 Selective ACK(수신 성공한 패킷의 개별 ACK 전송)을 받고 문제가 된 패킷만 재전송 115 | 116 |
117 |
118 | 119 |
120 | TCP 오류제어 121 |
122 | 123 | #### TCP 오류제어 124 | * TCP 오류 제어는 수신자와 송신자의 패킷 오류 처리를 하는 방법 125 | * 수신자가 송신자에게 명시적으로 NACK(부정응답)을 보내거나 송신자에게 ACK(긍정응답)가 오지 않거나 중복된 ACK가 계속 해서 오면 오류가 발생했다고 판단 126 | 127 | #### 종류 128 | 129 | ##### Stop and Wait ARQ 130 | ![image](https://user-images.githubusercontent.com/38535571/230089063-3f38e92f-18c8-4fe0-960f-574930b1b7c2.png) 131 | * 송신 측에서 1개의 프레임을 송신하고, 수신측에서 수신된 프레임의 에러 유무에 따라 ACK 혹은 NAK를 보내는 방식 132 | 133 | ##### Go Back N ARQ과 SR(Selective-Reject) ARQ 134 | ![image](https://user-images.githubusercontent.com/38535571/230089122-4e131f97-3c44-4a69-bf3d-76feb0c46f7d.png) 135 | 136 | * Go Back N ARQ: 전송된 프레임이 손상되거나 분실된 경우 그리고 ACK 패킷의 손실로 인한 타임아웃이 발생한 경우에 확인된 마지막 프레임 이후로 모든 프레임을 재전송하는 방식 137 | * SR(Selective-Reject) ARQ: 손실된 프레임만 재전송하여 Go Back N ARQ의 확인된 마지막 프레임 이후의 모든 프레임을 재전송하는 단점을 보완한 기법 138 | 139 |
140 |
141 | 142 |
143 | TCP 혼잡제어 144 |
145 | 146 | #### TCP 혼잡제어 147 | * `송신자와 네트워크(라우터)`의 데이터 처리 속도 차이를 해결하기 위한 방법 148 | * 패킷 손실 시 파악되는 타임 아웃이나 중복된 ACK을 통해서 혼잡을 파악 149 | * ACK을 확인하지 않고도 보낼 수 있는 데이터 양인 CWND(Congestion Window)를 기반으로 동작 150 | 151 | #### 종류 152 | 153 | ##### Additive Increase/Multicative Decrease 154 | ![image](https://user-images.githubusercontent.com/38535571/230089448-878526f9-afab-4fb3-a575-96af91da0c6e.png) 155 | * CWND를 기본 값에서 시작하여 1씩 증가시키는 방법 156 | 157 | ##### Slow Start 158 | ![image](https://user-images.githubusercontent.com/38535571/230089559-d3a441a1-9710-4762-b077-1e25420113be.png) 159 | * CWND가 1부터 지수적(2배)으로 증가시키는 방법 160 | ##### Congestion Avoidance(혼잡 회피) 161 | * CWND가 임계치에 도달하면 1씩 증가키는 방법 162 | 163 | ##### Fast Recovery(빠른 회복) 164 | * 혼잡 상황에서 사용되는 기법으로 CWND를 1/2배로 감소하고 선형적 증가시키는 방법 165 | ##### Fast Retransmit(빠른 재전송) 166 | * 중복 ACK를 3개 받으면 재전송을 하는 방법 167 | 168 |
169 |
170 | 171 |
172 | TCP 3-Way Handshake 173 |
174 | 175 | #### TCP 3-Way Handshake 176 | ![image](https://user-images.githubusercontent.com/38535571/230090204-4d27034e-9954-4a5a-b14b-105cf1bcafef.png) 177 | * 서버와 클라이언트가 TCP `연결을 맺을 때` 사용 178 | 179 | #### TCP 3-Way Handshake 과정 180 | * 클라이언트는 서버로 통신을 시작하겠다는 SYN을 보낸다. 181 | * 서버는 그에 대한 응답으로 SYN+ACK를 보낸다. 182 | * 마지막으로 클라이언트는 서버로부터 받은 패킷에 대한 응답으로 ACK를 보낸다. 183 | 184 | #### TCP 3-Way Handshake 상태 185 | 186 | * LISTEN: 포트가 열린 상태로 연결 요청 대기 중인 상태 187 | * SYN-SENT: SYN 요청을 한 상태 188 | * SYN-RECEIVED: SYN 요청을 받고 상대방의 응답을 기다리는 중인 상태 189 | * ESTABLISEHD: 연결의 수립이 완료된 상태, 서로 데이터를 교환할 수 있음 190 | 191 | #### 필요성 192 | * TCP는 양방향 프로토콜이므로 클라이언트와 서버가 각각 서로에게 패킷을 전송할 수 있다는 것을 확인해야 됨 193 | 194 | #### Sequence Number를 난수로 이용하는 이유 195 | * 연결을 맺을 때 사용하는 포트(port)는 유한 범위 내에서 사용하고 시간이 지남에 따라 재사용됨 196 | * 따라서 두 통신 호스트가 과거에 사용된 포트 번호 쌍을 사용할 가능성이 존재함 197 | * 서버 측에서는 패킷의 SYN을 보고 패킷을 구분하게 되는데, 난수가 아닌 순차적인 number가 전송된다면 이전의 연결로부터 오는 패킷으로 인식할 위험이 있음 198 | 199 |
200 |
201 | 202 |
203 | TCP 4-Way Handshake 204 |
205 | 206 | #### TCP 4-Way Handshake 207 | ![image](https://user-images.githubusercontent.com/38535571/230090283-f712544c-4d3d-43c8-b751-3ce893704e20.png) 208 | * 서버와 클라이언트가 TCP `연결을 종료할 때` 사용 209 | 210 | #### TCP 4-Way Handshake 과정 211 | * 클라이언트는 응답을 주고 연결을 끊기 위해 FIN패킷을 보낸다. 212 | * 서버는 클라이언트에서 보낸 패킷에 대한 응답으로 ACK 패킷을 보낸다. 213 | * 서버는 자신의 통신이 모두 끝나면 사용한 소켓을 정리하며 통신을 완전히 끝내도 된다는 의미로 FIN 패킷을 보낸다. 214 | * 클라이언트는 서버 패킷에 대한 응답으로 ACK패킷을 보낸다. 215 | 216 | #### TCP 4-Way Handshake 상태 217 | * CLOSE-WAIT 상대방의 FIN(종료 요청)을 받은 상태 (상대방 FIN에 대한 ACK를 보내고 애플리케이션에 종료를 알림) 218 | * FIN-WAIT-1 자신이 보낸 FIN에 대한 ACK를 기다리거나 상대방의 FIN을 기다리는 상태 219 | * LAST-ACK CLOSE-WAIT 상태를 처리 후 자신의 FIN요청을 보낸 후 FIN에 대한 ACK를 기다리는 상태 220 | * FIN-WAIT-2 자신이 보낸 FIN에 대한 ACK를 받았고 상대방의 FIN을 기다리는 상태 221 | * TIME-WAIT 모든 FIN에 대한 ACK를 받고 연결 종료가 완료된 상태 (새 연결과 겹치지 않도록 일정 시간 동안 기다린 후 CLOSED로 전이) 222 | * CLOSE 연결 수립을 시작하기 전의 기본 상태 (연결 없음) 223 | 224 | #### 필요성 225 | * 클라이언트가 일방적으로 끊으면 서버는 `연결은 되어 있으나 요청이 없는 상태`로 오해할 수 있음 226 | * 클라이언트는 데이터 전송을 끝냈다고 하더라도 서버는 전송할 것이 남아있을 수 있음 227 | 228 |
229 |
230 | 231 |
232 | IP 주소 체계 233 |
234 | 235 | #### IPv4 236 | * 현재 일반적으로 사용되는 주소 체계 237 | * 32비트를 8비트로 단위로 점을 찍어 표기하는 방식 238 | * 123.45.67.88 같은 방식으로 표기됨 239 | 240 | #### IPv6 241 | * IPv4의 주소의 개수가 부족 문제를 해결하기 위해 생긴 주소 체계 242 | * 64비트를 16비트 단위로 점을 찍어 표기하는 방식 243 | * 2001:db8::ff00:42:8329 같은 방식으로 표기됨 244 | 245 | 246 | #### IPv4 IPv6 헤더 247 | ![image](https://user-images.githubusercontent.com/38535571/230091358-80da4098-409a-4315-afa2-0b7fd03b7513.png) 248 | 249 | #### IPv4 IPv6 패킷 250 | ![image](https://user-images.githubusercontent.com/38535571/230091472-20cb9246-77ef-47e2-9401-597a7e51d130.png) 251 | ![image](https://user-images.githubusercontent.com/38535571/230091539-a2455449-b874-466c-8b37-9fe6d5af24b8.png) 252 | 253 |
254 |
255 | 256 |
257 | 클래스 기반 할당 방식 258 |
259 | 260 | #### 클래스 기반 할당 방식 261 | ![image](https://user-images.githubusercontent.com/38535571/230091833-02061247-24a4-4a54-bce3-d8dbf125f81b.png) 262 | * 클래스를 구분하여 대역을 설정하여 앞에 있는 부분을 네트워크 주소, 그 뒷 부분을 주소인의 호스트 주소로 IP를 활용하는 방법 263 | * A 클래스의 12.0.0.0 네트워크를 부여받았다면 12.255.255.255.255는 브로드 캐스트용 주소가 되며 12.0.0.1 ~ 12.255.255.255.254의 호스트 주소로 사용 가능 264 | * 116.0.0.0 네트워크를 부여받았다면 A 클래스이며 116.0.0.1 ~ 12.255.255.255.254의 호스트 주소로 사용 가능 265 | 266 | #### 클래스 A 267 | * 앞에 첫번째 바이트를 네트워크 주소로 나머지 3개의 바이트를 호스트 주소로 사용 268 | * 구분 비트가 0 -> 00000000.00000000.00000000.00000000 ~ 01111111.11111111.11111111.11111111 269 | * 대역 0.0.0.0 ~ 127.255.255.255 사용 270 | 271 | #### 클래스 B 272 | * 앞에서부터 두번째 바이트까지를 네트워크 주소로 나머지 2개의 바이트를 호스트 주소로 사용 273 | * 구분 비트가 10 -> 10000000.00000000.00000000.00000000 ~ 10111111.11111111.11111111.11111111 274 | * 대역 128.0.0.0 ~ 191.255.255.255 사용 275 | 276 | #### 클래스 C 277 | * 앞에서부터 세번째 바이트까지를 네트워크 주소로 나머지 1개의 바이트를 호스트 주소로 사용 278 | * 구분 비트가 110 -> 11000000.00000000.00000000.00000000 ~ 11011111.11111111.11111111.11111111 279 | * 대역 192.0.0.0 ~ 223.255.255.255 사용 280 | 281 |
282 |
283 | 284 |
285 | CIDR (Classless Inter-Domain Routing) 방식 286 |
287 | 288 | ![image](https://user-images.githubusercontent.com/38535571/230092405-0fa92be9-3fc4-43a0-a6b3-30e51d0441b1.png) 289 | 290 | * 클래스 없는 도메인 간 라우팅 기법 291 | * 최신의 IP 주소 할당 방법으로 정적이였던 클래스 방식에 비해 IP 주소의 영역을 여러 네트워크 영역으로 나눌 수 있기 때문에 기존방식에 비해 유연 292 | * 서브넷으로 최대 호스트 수를 유추할 수 있음 293 | * 예를 들면 10.0.2.23/xx 같은 형식 294 | * xx 자리수까지는 고정 IP 295 | * 서브넷의 사용 가능 IP 수: 2^(32-xx) - 2 296 | * 첫번째: 네트워크 주소, 마지막: 브로드캐스팅 주소 297 | * 네트워크가 143.7.65.203/22 이면 앞에 22비트는 네트워크 주소를 나타내고 나머지 10비트는 호스트 주소를 나타내고 143.7.64.0 ~ 143.7.67.255의 호스트 주소를 사용 298 |
299 |
300 | 301 |
302 | NAT (Network Address Translation) 303 |
304 | 305 | ![image](https://user-images.githubusercontent.com/38535571/230092496-4cd47fc8-ea85-4f8e-b47b-82f74572f901.png) 306 | 307 | #### 정의 308 | * IP 패킷의 TCP/UDP 포트 숫자와 소스 및 목적지의 IP 주소 등을 `재기록`하면서 `라우터`를 통해 통신하는 기술 309 | * 외부에 공개된 `공인(Public) IP`와 내부에서 사용하는 `사설(Private) IP`를 `맵핑`하여 원활히 통신할 수 있게 하는 기술 310 | * IPv4 주소 체계로 많은 주소를 표기하지 못했는데 이를 해결해준 기술 311 | * 사설 IP를 통하기 때문에 내부망 IP들이 노출되지 않으므로 보안적 강점이 있음 312 | * 외부에서 사설 IP를 알 방법이 없어 내부 네트워크와 호스트를 보호 가능 313 | 314 | #### 동작 과정 315 | ##### 요청 패킷 전송하기 316 | * 패킷 헤더 = `소스 IP: 사설 IP`, `목적 IP: 목적지 IP` 317 | * 게이트 웨이에서 `소스 IP: 게이트웨이의 공인 IP`로 변경, `목적 IP: 목적지 IP` 변경 없음 318 | * NAT 테이블에 맵핑 내역을 저장 319 | 320 | ##### 응답 패킷받기 321 | * 패킷 헤더 = `소스 IP: 목적지 IP`, `목적 IP: 게이트웨이의 공인 IP` 322 | * 게이트 웨이에서 `소스 IP: 목적지 IP` 변경 없음, `목적 IP: 사설 IP`로 변경 (재기록) 323 | * NAT 테이블을 참조하여 수정 324 | 325 |
326 |
327 | 328 |
329 | CDN (Contents Delivery Network) 330 |
331 | 332 | #### CDN 333 | * `지리적, 물리적으로 떨어져 있는` 사용자에게 웹 페이지 콘텐츠 `로드 지연을 최소화`하는 촘촘히 `분산된 서버`로 이루어진 플랫폼 기술 334 | * 각 지역에 캐시 서버(PoP, Points of Presence)를 분산 배치해서 가까운 사용자의 요청에 원본 서버가 아닌 캐시 서버가 콘텐츠를 전달 335 | 336 | #### CDN 사용 시의 이점 337 | * 지리적으로 가까운 캐시 서버가 응답하여 빠른 응답 가능 338 | * Origin 서버에 문제가 생겨도 다른 서버로 대체가 가능해 안전성 증가 339 | * 트래픽 집중 방지 가능 340 | 341 | #### CDN 처리 과정 342 | * 클라이언트는 HTML, 이미지, CSS, JavaScript 파일 등 필요한 콘텐츠를 요청 343 | * `콘텐츠에 대한 각 요청이 발생하면 최적으로 배치된 CDN 서버에 엔드유저가 매핑` 344 | * CDN 서버는 요청된 파일의 `캐싱`된(사전 저장된) 버전으로 응답 345 | 346 |
347 |
348 | 349 |
350 | DNS (Domin Name System) 351 |
352 | 353 | ![image](https://user-images.githubusercontent.com/38535571/230093255-b1d91c83-b6e0-4410-96c7-05d9c03c085d.png) 354 | 355 | #### 도메인 356 | * 네트워크 상에서 컴퓨터를 식별하는 호스트명 357 | 358 | #### DNS 359 | * 컴퓨터를 식별하는 호스트명인 도메인을 실제 서버와 연결 시켜주는 시스템 360 | 361 |
362 |
363 | 364 |
365 | GSLB (Global Server Load Balancing) 366 |
367 | 368 | ![image](https://user-images.githubusercontent.com/38535571/230092667-f2fbf5e6-bc34-44e4-97a2-0ea5ddd37376.png) 369 | 370 | * 전통적인 DNS 서비스를 발전시킨 형태로 헬스 체크와 지리적 정보를 사용하는 시스템 371 | * DNS 기반의 로드 밸런싱으로 IP가 아닌 도메인을 갖음 372 | * DNS와 VIP를 통해서 구성을 한 경우 한 IDC에 서버들이 몰려 있으면 DR 상황에서 문제가 생길 수 있기 때문에 서버의 위치를 고려할 수 있는 GSLB를 사용 373 | * VIP와 GLSB를 함께 사용 할 수도 있고 VIP 없이 GSLB만 서버에 묶어서 구성할 수도 있음 374 | * 일반적인 DNS 방식과 달리 헬스 체크를 통해서 서버가 죽은 경우 해당 서버로 요청이 가지 않도록 할 수 있음 375 | * 일반적인 DNS 방식과 달리 L4/L7의 스위치가 추가로 필요 376 | 377 |
378 |
379 | 380 | 381 |
382 | 로드 밸런싱 383 |
384 | 385 | ![image](https://user-images.githubusercontent.com/38535571/230092566-e9686218-692f-43ce-8d0a-65171baacace.png) 386 | 387 | #### 로드 밸런싱 388 | * 로드 밸런서를 클라이언트와 서버 사이에 두고, 부하가 집중되지 않도록 여러 서버에 분산하는 방식 389 | * Scale out 시에 사용 390 | * Server Load Balancing이라고도 불림 391 | 392 | #### 로드 밸런서 393 | * 로드 밸런싱 작업을 담당하는 장비 394 | 395 | #### 로드 밸런서의 역할 396 | * NAT(Network Address Translation): 사설IP - 공인IP 전환 397 | * Tunneling: 데이터를 캡슐화하여 연결된 노드만 캡슐을 해제할 수 있게 만듦 398 | * DSR(동적 소스 라우팅): 요청에 대한 응답을 할 때 로드밸런서가 아닌 클라이언트의 IP로 응답 399 | 400 | #### L4 로드 밸런싱 401 | * IP와 PORT 기반의 로드 밸런싱 402 | * 보통 L4 스위치 장비로 로드밸런싱하며 가격이 비쌈 403 | * VIP를 통한 로드 밸런싱은 L4 로드밸런싱 404 | 405 | #### L7 로드 밸런싱 406 | * URI, Payload, Http Header, Cookie 등 기반의 로드 밸런싱 407 | * 보통 L7 스위치 장비로 로드밸런싱하며 가격이 비쌈 408 | * nginx나 apache를 통한 로드 밸런싱은 L7 로드밸런싱 409 | 410 | #### VIP(Virtual IP) 411 | * 여러 개의 실제 서버를 대표하는 가상의 IP로 DNS와 VIP를 연결하여 다수의 서버에 연결할 때 사용 412 | * VIP는 IP 기반의 `로드 밸런싱`하는 역할을 겸할 수 있음 413 | 414 |
415 |
416 | 417 |
418 | FQDN 419 |
420 | 421 | * Fully Qualified Domain Name의 약자로 전체 `주소 도메인 네임` 422 | * 도메인 하위에 서브 도메인을 구성할 수 있는데 FQDN은 서브도메인까지 포함한 Full Domain 423 | 424 |
425 |
426 | 427 |
428 | ACL 429 |
430 | 431 | * Access Control List의 약자로 네트워크 망에 접근을 허가하는 IP 리스트와 포트 432 | 433 |
434 |
435 | 436 |
437 | Proxy 서버 438 |
439 | 440 | #### 프록시 441 | 442 | * 다른 서버와 통신하기 전에 반드시 거치도록 되어 있는 서버로 `클라이언트가 프록시를 통해서 다른 네트워크 서비스에 간접적으로 접속하게하는 서버 프로그램` 함 443 | * Access Control, Cache, 보안 등의 기능을 할 수 있음 444 | * 포워드 프록시라고 부르기도 함 445 | 446 | #### 리버스 프록시 447 | * 한 대 이상의 서버로부터 자원을 추출하여 클라이언트에 전달하는 프록시 서버 448 | * 부하 분산이 가능 449 | * 주로 웹 서버를 통해 리버스 프록시 서버를 구축 450 | 451 |
452 |
453 | 454 |
455 | CORS 456 |
457 | 458 | * 교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제 459 | 460 |
461 |
462 | 463 |
464 | 웹 브라우저에 URL을 입력했을 때의 수행 과정 465 |
466 | 467 | * 사용자의 PC는 `DHCP 서버`에서 사용자 `자신의 IP 주소`, `가장 가까운 라우터의 IP 주소`, `가장 가까운 DNS서버의 IP 주소`를 받음 468 | * `DNS` 서버로 쿼리를 전송해 URL의 `IP 주소`를 응답받음 469 | * `ARP`를 이용하여 가장 가까운 라우터의 IP 주소로 MAC 주소를 얻어 요청 전송 470 | * TCP Socket을 통해 웹 서버와 `3-Way Hand Shaking`을 하여 연결 471 | * `HTTP Request`가 TCP Socket을 통해 보내지고, 응답으로 웹페이지의 정보가 사용자의 PC에 전달 472 | 473 | #### 참고 474 | * DHCP: IP 주소 및 TCP/IP 설정을 클라이언트에 자동으로 제공하는 프로토콜 475 | * DNS: IP 주소와 도메인의 매핑 정보를 관리하는 프로토콜 476 | * ARP: IP 주소를 물리 주소로 변환하는 프로토콜 477 | * IP 주소: 컴퓨터 마다 부여된 고유의 주소, 변할 수 있음 478 | * MAC 주소: NIC 카드 마다 부여된 네트워크 장비 고유의 주소, 변하지 않음 479 | 480 |
481 |
482 | -------------------------------------------------------------------------------- /OOP/README.md: -------------------------------------------------------------------------------- 1 | # OOP(Object-Oriented Programming) 2 | 3 |
4 | 5 |
6 | C, C++, JAVA, Python 7 |
8 | 9 | * C 10 | * 컴파일 언어이자 절차지향 언어 11 | * C++: 컴파일 언어이자 객체지향 언어 12 | * C의 상위 호환으로 객체를 활용하는 기능이 있음 13 | * 각 OS에 맞는 기계어로 변환해 실행(속도 빠름) 14 | * 메모리를 직접 관리할 수 있음 15 | * JAVA 16 | * 컴파일 언어이자 객체지향 언어 17 | * 기본 단위가 Class로 완전한 OOP 언어 18 | * 가상머신에서 실행하여 OS와 독립적이며 가비지 콜렉션을 지원 19 | * Python 20 | * 인터프리터 언어 21 | * 코드를 한줄씩 번역해 실행 22 | * 객체를 활용하는 기능이 있음 23 | 24 |
25 |
26 | 27 | 28 |
29 | 객체지향 프로그래밍과 장점 30 |
31 | 32 | * 프로그래밍에서 필요한 데이터를 `추상화`시켜 상태와 행위를 가진 `객체`를 만들고 그 객체들 간의 유기적인 `상호작용`을 통해 로직을 구성하는 프로그래밍 방식 33 | * `추상화`가 쉽고 `상속`을 통해 코드 `재산성성`을 높일 수 있으며 객체 단위로 코드가 나눠져 있기 때문에 `디버깅과 유지보수`에 용이 34 | 35 |
36 |
37 | 38 |
39 | 객체지향 프로그래밍의 특징 40 |
41 | 42 | * `추상화`: 복잡한 시스템에서 핵심적인 것을 간추리는 것을 의미 43 | * 하위클래스들에 존재하는 공통적인 메소드를 `인터페이스`로 정의 44 | * `캡슐화`: 객체의 속성과 기능을 하나로 묶고 일부를 외부에 감추어 `은닉`하는 것을 의미 45 | * `private`으로 멤버 변수 선언, 해당 변수에 접근하는 별도의 함수 정의 46 | * `상속`: 상위 클래스의 특성을 하위 클래스가 이어 받아서 재사용 또는 확장하는 것을 의미 47 | * 코드 재사용 48 | * `다형성`: 하나의 메서드나 클래스가 다양한 방법으로 동작하는 것을 의미 49 | * 상위 클래스: 추상 클래스, 함수: 추상 함수 50 | * 하위 클래스: 상위 클래스의 함수를 자신의 목적에 맞게 서로 다른 방법으로 구현 51 | 52 |
53 |
54 | 55 |
56 | 객체 57 |
58 | 59 | #### 객체 60 | * 데이터(변수)와 데이터의 동작(함수, 절차, 기능)을 모두 포함한 개념 61 | 62 | #### 객체의 종류 63 | - VO(Value Object): 불변 객체, 동일하게 생성된 VO는 항상 동일한 상태여야하며 인스턴스화된 VO는 항상 유효한 값을 리턴해야함 64 | - DTO(Data Transfer Object): 데이터 전송 객체, 상태를 보호하지 않으며 모든 속성을 노출하는 객체 65 | - Entity: 유일한 식별자가 있는 객체로 보통 데이터 베이스에 저장 66 | - DAO(Data Access Object, Repository): 데이터 베이스에 접근할 때 사용하는 추상 객체 67 | - BO(Business Object, Service): 비지니스 로직이 들어있는 객체 68 | 69 |
70 |
71 | 72 |
73 | 관계 74 |
75 | 76 | #### 관계 77 | * 클래스 간의 속성, 지역 객체, 메소드 인자, 상속, 인터페이스 등의 형태로 맺는 관계를 의미 78 | 79 | #### 관계의 종류 80 | - 연관 관계: 한 클래스가 다른 클래스에서 제공하는 기능을 사용하는 상황에서 계속 그 관계가 유지되는 관계 81 | - 일반화 관계: 객체지향 개념에서 상속 관계와 같은 의미, is a kind of 82 | - 집합 관계: 클래스들 사이의 전체 또는 부분 같은 관계 83 | - 의존 관계: 한 클래스가 다른 클래스에서 제공하는 기능을 사용하는 상황에서 실행하는 동안만 그 관계가 유지되는 관계 84 | - 실체화 관계: 객체지향 개념에서 인터페이스와 이를 실현한 클래스들의 관계, can do this 85 |
86 |
87 | 88 |
89 | 디미터 법칙 90 |
91 | 92 | * 디미터 법칙: 최소 지식의 법칙, 모듈은 자신이 조작하는 객체의 속사정을 몰라야한다는 원칙으로 여러 개의 .(도트)를 사용하지 말라는 법칙으로 불림 93 | 94 |
95 |
96 | 97 |
98 | CQRS 99 |
100 | 101 | * CQRS(Command and Query Responsibility Segregtaion): 하나의 메소드는 명령이나 쿼리여야하며 두 가지 기능을 모두 가져서는 안된다는 이론으로 명령은 객체의 상태를 변경할 수 있지만 값을 반환하지 않고 쿼리는 값을 반환하지만 객체를 변경하지 않음 102 | 103 |
104 |
105 | 106 |
107 | TDA 원칙 108 |
109 | 110 | * TDA 원칙(Tell Dont Ask): 물어보지 말고 그냥 시켜라, 객체와 객체가 협력하는 경우 다른 객체의 정보를 요구하지 말고 그냥 행위하도록 시키라는 의미 111 | * 객체의 상태를 조회하는 메서드를 없애고 상태에 대한 판단 자체를 하는 메서드를 만드는 것은 권장하는 원칙 112 | 113 |
114 |
115 | 116 | 117 |
118 | Overriding과 Overloading 119 |
120 | 121 | * 오버라이딩: 부모 클래스에 존재하는 메서드를 자식 클래스에서 재정의하는 것 122 | ```java 123 | SuperClass super = new SubClass(); 124 | super.function(); // SubClass의 함수 실행 125 | ``` 126 | 127 | * 오버로딩: 같은 이름의 메소드를 여러 개 정의, 매개변수의 타입이나 개수가 달라야 함 128 | 129 |
130 |
131 | 132 | 133 |
134 | 객체지향 설계의 5원칙 135 |
136 | 137 | * `SRP(Single Responsibility Principle)`: 단일 책임 원칙, 클래스는 단 하나의 책임을 가져야 하며 클래스를 변경하는 이유는 단 하나의 이유이어야 한다. 138 | * `OCP(Open-Closed Principle)`: 개방-폐쇄 원칙, 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다. 139 | * 추상화(인터페이스) 140 | * `LSP(Liskov Substitution Principle)`: 리스코프 치환 원칙, 상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다. 141 | * 자식 클래스는 언제나 자신의 부모 클래스를 대체할 수 있다는 원칙이다 142 | * 자식 클래스가 부모 클래스의 기존 메소드의 의미를 해치지는 않는다. 143 | * 보통 상속보단 컴포지션을 사용해라. 144 | * `ISP(Interface Segregation Principle)`: 인터페이스 분리 원칙, 인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다. 145 | * 인터페이스는 public으로 선언된 메서드이다. 146 | * 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다는 원칙 147 | * 일반적인 한 개의 인터페이스보다 구체적인 여러가지의 인터페이스를 구현하는 원칙 148 | * `DIP(Dependency Inversion Principle)`: 의존 역전 원칙, 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다. 149 | * 변하지 않는 객체에 의존한다. 150 | * 상위 클래스, 인터페이스, 추상 클래스일수록 변하지 않을 가능성이 높기에 하위 클래스나 구체(concrete) 클래스가 아닌 상위 클래스, 인터페이스, 추상 클래스에 의존한다. 151 | 152 |
153 |
154 | 155 |
156 | 의존성 주입 157 |
158 | 159 | #### 의존 160 | * 기능 구현을 위해 다른 구성 요소를 사용하는 것 161 | * 객체 생성, 메서드 호출, 데이터 사용 162 | #### 의존성 주입 163 | * 의존성에 필요한 값을 외부에서 파라미터로 받아 넣어주는 것 164 | 165 | #### 의존성 주입의 방법 166 | * 수정자 주입: Setter를 통해서 필드에 의존성을 주입하는 것 167 | * 생성자 주입: 생성자를 호츨 할 때 의존성을 주입하는 것 168 | * 필드 주입: DI 프레임워크가 필수적으로 필요한 방법으로 필드에 맞는 프레임워크에 의해 의존성을 주입하는 것 169 | 170 | #### 조립기 171 | * 객체 생성 및 의존 주입을 처리해주는 모듈 172 | * 스프링 프레임워크에서 ApplicationContext가 이 역할을 수행 173 | 174 | #### 의존성 주입 장점 175 | * 의존 대상이 바뀌면 조립기 설정만 변경하면 가능 176 | * 의존하는 객체 없이 대역 객체를 사용해서 테스트가 가능 177 | 178 |
179 |
180 | 181 | 182 |
183 | 클래스와 인스턴스의 차이 184 |
185 | 186 | * 클래스는 객체를 만들기 위한 템플릿, 객체는 클래스라는 템플릿을 토대로 `메모리에 할당한 실체` 187 | * 클래스: `객체를 만드는 틀`, 객체의 속성과 기능(행위)을 정의 188 | * 객체: `클래스라는 틀에서 생겨난 실체`, 속성(멤버 변수)과 기능(메소드, 함수)의 집합 189 | 190 |
191 |
192 | 193 |
194 | 상속과 인터페이스의 차이 195 |
196 | 197 | * 상속 198 | * 상속은 확장해서 사용할 수 있다는 의미 199 | * 상위 클래스에서 구현된 메서드는 모든 하위 클래스의 객체에서 사용 가능 200 | * 올바른 상속의 설계는 is a kind of 관계(하위 클래스 is a kind of 상위 클래스)를 만족해야함 201 | * 인터페이스 202 | * 행위에 대한 기능을 강제한다는 의미 203 | * 올바른 인터페이스의 설계는 be able to 관계를 만족해야함 204 | 205 |
206 |
207 | 208 |
209 | 결합도와 응집도의 차이 210 |
211 | 212 | * 결합도 213 | * 클래스(모듈) 간의 상호 의존 정도 214 | * 결합도가 낮으면 모듈 간의 상호 의존성이 줄어들어 객체의 재사용이나 수정 및 유지보수가 용이 215 | * 응집도 216 | * 클래스(모듈) 내부에 존재하는 구성 요소들의 기능적 관령성 217 | * 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정 및 유지보수가 용이 218 | 219 |
220 |
221 | 222 | 223 |
224 | Immutable 225 |
226 | 227 | * 생성 후 변경 불가한 객체로 변경을 하려면 복사 이후 변경해야함 228 | 229 |
230 |
231 | 232 |
233 | 순환 참조 234 |
235 | 236 | * 순환 참조: 각각의 객체가 서로를 참조하고 있는 상태 237 | * 객체의 Serializable을 불가능하게 만들고 JPA의 mappedby에서 신경을 추가로 써야함 238 | 239 |
240 |
241 | 242 | -------------------------------------------------------------------------------- /OS/README.md: -------------------------------------------------------------------------------- 1 | # OS 2 | 3 |
4 | 5 |
6 | 운영체제 정의 7 |
8 | 9 | * 하드웨어(CPU, 메모리, 디스크 등)를 관리 10 | * `응용 프로그램과 하드웨어 사이에서 인터페이스 역할`을 하는 시스템 소프트웨어 11 | * 시스템의 자원과 동작을 관리하는 소프트웨어 12 | * 프로세스, 저장장치, 네트워킹, 사용자, 하드웨어 관리 13 | 14 |
15 |
16 | 17 | 18 |
19 | 프로세스와 스레드의 차이 20 |
21 | 22 | * 프로세스는 `실행중인 프로그램`으로 OS로부터 자원을 할당받아 실행, `코드/데이터/스택/힙` 메모리 영역을 가짐 23 | * `프로세스의 독립적인 실행 단위`로 프로세스로부터 자원을 할당받아 실행, 프로세스의 `코드/데이터/힙` 메모리 영역을 공유하고 `개별적인 스택`을 가짐 24 | 25 |
26 |
27 | 28 | 29 |
30 | 스레드가 개별적인 스택을 가지는 이유 31 |
32 | 33 | * 스택에는 함수 호출 시의 전달인자, 지역 변수, 되돌아갈 주소 등을 저장 34 | * 독립적인 스택을 갖는 것은 독립적인 함수 호출이 가능하고 독립적인 실행 흐름을 추가할 수 있다는 것을 의미 35 | 36 |
37 |
38 | 39 | 40 |
41 | 스레드가 PC 레지스터를 가지는 이유 42 |
43 | 44 | * 스레드는 CPU를 할당/반납하고를 반복 45 | * 이전까지의 수행 내역을 기억하기 위해 독립적인 PC 사용 46 | 47 |
48 |
49 | 50 | 51 |
52 | 프로세스 메모리 구성 53 |
54 | 55 | * 코드: 프로그램의 코드 저장 56 | * 데이터: 전역 변수, 정적 변수 저장 57 | * 스택: 지역 변수, 매개 변수, 함수의 호출과 할당, `컴파일`에 크기 결정 58 | * 힙: 동적으로 할당 및 해제, `런 타임`에 크기 결정 59 | 60 |
61 |
62 | 63 |
64 | 힙과 스택의 차이 65 |
66 | 67 | * 힙: 프로그램 코드에서 `동적으로 할당`하여 사용되는 메모리 영역 68 | * 스택: `함수를 호출`할 때나 `지역변수`를 지정할 때 `자동`으로 할당되는 메모리 영역 69 | 70 |
71 |
72 | 73 |
74 | 스택의 장점과 단점 75 |
76 | 77 | * 장점: 자동으로 처리되기 때문에 `낭비되는 공간이 없고` 사용하기가 편리 78 | * 단점: 한계가 있어 한계를 초과하도록 삽입할 수 없고 `유연성이 부족` 79 | 80 |
81 |
82 | 83 |
84 | 힙의 장점과 단점 85 |
86 | 87 | * 장점: 프로그램에 필요한 개체의 개수나 크기를 미리 알 수 없는 경우 사용하고 개체가 너무 커서 스택 할당자에 맞지 않는 경우 사용 가능 88 | * 단점: `할당/해제 작업`으로 인한 속도 저하 89 | 90 |
91 |
92 | 93 | 94 |
95 | 프로세스 생성과정 96 |
97 | 98 | * 프로세스 관리 정보를 갖는 `Process Control Block를 생성`하고 프로그램의 코드를 읽어 들여 `코드 영역`을 메모리에 할당 99 | * 초기화된 전역 변수 및 static 변수인 `데이터 영역`을 메모리에 할당 100 | * `힙과 스택의 초기 메모리 주소를 초기화` 101 | * `Queue에서 프로세스가 등록`되고 운영체제가 CPU를 할당하기를 대기 102 | 103 |
104 |
105 | 106 | 107 |
108 | PCB (Process Control Block) 109 |
110 | 111 | * `프로세스 관리 정보`를 저장하는 커널의 자료구조 (Data 영역에 존재) 112 | * Process 상태, PC(다음에 수행할 명령어의 주소), CPU 레지스터, CPU 스케줄링 정보, 메모리 관리 정보 등을 저장 113 | * `문맥 교환` 시에 진행 사항을 PCB에 저장하고 CPU 반환 -> CPU를 할당받으면 PCB에 저장되어 있는 내용을 불러와 이전에 종료되었던 시점부터 다시 수행 114 | 115 |
116 |
117 | 118 | 119 |
120 | 문맥 교환 (Context Switching) 121 |
122 | 123 | ![image](https://user-images.githubusercontent.com/38535571/230786507-6be6a4c9-f212-466d-9918-781ab2e69125.png) 124 | 125 | * 실행 중이던 프로세스를 중단하고 다른 프로세스를 실행할 때 발생 126 | * 프로세스 사이에서 `CPU 제어권`이 이동되는 것 127 | * 문맥: CPU에서 프로세스를 실행하는데 필요한 프로세스의 정보, 각 프로세스의 `PCB`에 저장 128 | * 멀티 스레드에서는 문맥 교환 시 스택 영역을 제외한 모든 영역을 공유하기 때문에 문맥 교환 비용이 훨씬 적음 129 | * 과정 130 | 1. 실행 중이던 프로세스의`상태(문맥)를 PCB에 보관`
131 | 2. 새로운 프로세스의 `PCB에서 문맥(Context)을 복원`해 레지스터에 적재
132 | 3. 새로운 프로세스 실행 133 | 134 |
135 |
136 | 137 | 138 |
139 | 인터럽트 140 |
141 | 142 | * 프로그램을 실행하는 도중에 예기치 않은 상황이 발생할 경우 `현재 실행 중인 작업을 즉시 중단`하고, `발생된 상황을 우선 처리`한 후 `실행 중이던 작업으로 복귀`하여 계속 처리하는 것 143 | * 문맥 교환을 구현할 때 `Timer Interrupt`를 통해서 제어권을 커널이 가져올 수 있도록 활용 144 | 145 |
146 |
147 | 148 | 149 |
150 | 멀티 프로세스 151 |
152 | 153 | * 여러 `프로세서`(CPU)가 여러 작업(Task)을 동시에 처리하는 것 (병렬 처리) 154 | * `안전성`: 하나의 프로세스가 죽더라도 다른 프로세스에는 영향을 끼치지 않고 정상적으로 수행 155 | * 통신 비용/문맥 교환 `비용이 큼` 156 | * CPU는 한 번에 하나의 프로세스만 실행 가능 -> 여러 프로세스를 돌아가면서 실행 157 | * IPC (Inter Process Communication): 프로세스 간의 통신을 하는 것 158 | * 파일 공유, 커널 영역 이용(메시지 큐, 공유 메모리, 소켓 등) 159 | * `많은 메모리 공간`을 차지 160 | 161 |
162 |
163 | 164 | 165 |
166 | 멀티 스레드 167 |
168 | 169 | * 하나의 프로세스에 여러 스레드가 자원을 공유하며 작업을 나누어 하는 것 170 | * `안전성 낮음`: 하나의 스레드의 비정상적인 활동은 전체 스레드에 영향을 끼칠 수 있음 171 | * 통신 비용 적음 172 | * `코드/데이터/힙 영역을 공유`해 `메모리를 적게 차지`하고 공유 메모리가 없어도 통신 가능 173 | * 문맥 교환 비용 적음 174 | * 프로세스를 생성하여 자원을 할당하는 시스템 콜이 감소함으로서 `자원을 효율적으로 관리` 175 | 176 | 177 |
178 |
179 | 180 | 181 |
182 | Thread Safe 183 |
184 | 185 | * 멀티 스레딩에서 하나의 자원에 여러 스레드가 동시에 접근해도 프로그램 실행의 문제가 없는 상태 186 | * Thread Safe한 코드: `Critical Section`을 통해 스레드 내부에서 처리되는 연산들을 `직렬화(Serialize)` 하여 한 번에 한 스레드에서 연산이 수행 187 | 188 |
189 |
190 | 191 | 192 |
193 | 병렬성과 동시성의 차이 194 |
195 | 196 | * 병렬성: `멀티 코어`에서의 멀티 스레드, 각 코어들의 스레드가 동시에 실행 197 | * 동시성: `싱글 코어`에서의 멀티 스레드, 여러 개의 스레드가 번갈아가며 실행 198 | 199 |
200 |
201 | 202 | 203 |
204 | Critical Section(공유 자원, 임계 영역) 205 |
206 | 207 | * 동일한 자원에 동시에 접근하는 경우가 발생하는 코드 영역 208 | * 접근 순서에 따라 실행 결과가 달라지는 구역 209 | 210 |
211 |
212 | 213 | 214 |
215 | Race Condition 216 |
217 | 218 | * 공유 자원에 여러 프로세스/스레드가 접근할 경우 `접근 순서에 따라 결과가 달라지는 현상` 219 | 220 |
221 |
222 | 223 | 224 |
225 | 뮤텍스와 세마포어 226 |
227 | 228 | * `상호 배제`를 달성하는 기법 229 | * 상호 배제: 둘 이상의 프로세스/스레드가 동시에 임계 영역에 진입하는 것을 방지하기 위해 사용하는 알고리즘 230 | * 상호 배제만 필요하면 뮤텍스, 실행 순서 동기화 또는 두개 이상의 프로세스/스레드가 접근해야 되면 세마포어를 사용 231 | 232 | #### 뮤텍스 (Mutual Exclusion) 233 | * `동기화 대상이 1개`일 때 사용 -> 1개 프로세스/스레드만 접근 가능 234 | * `바이너리 세마포어`와 비슷함 235 | * 자원 소유 가능: `락`을 소유한 스레드만이 락을 반환할 수 있음 236 | * `Deadlock`이 발생할 수 있음 237 | 238 | #### 세마포어 (Semaphore) 239 | * `동기화 대상이 여러 개`일 때 사용 -> `세마포어 변수(Counter)`만큼의 프로세스/스레드 접근 가능 240 | * 1: 바이너리 세마포어 241 | * 2 이상: 카운팅 세마포어 242 | * Signaling mechanism 243 | * wait(): 세마포어 변수 1감소 -> Critical Section -> signal(): 세마포어 변수 1증가 244 | * 자원 소유 불가: wait()와 signal()을 호출하는 존재가 다를 수 있음 245 | * `Deadlock`이 발생할 수 있음 246 | 247 |
248 |
249 | 250 | 251 |
252 | 뮤텍스와 모니터 253 |
254 | 255 | #### 뮤텍스 256 | * 다른 프로세스간 동기화에 사용 가능 257 | 258 | #### 모니터 259 | * 하나의 프로세스 내에서 `스레드 간의 동기화` 260 | * 프레임워크나 라이브러리 자체에서 제공 261 | * C언어는 없고 Java는 있음 262 | 263 |
264 |
265 | 266 | 267 |
268 | 교착 상태(Deadlock) 정의와 발생 조건, 해결 방법 269 |
270 | 271 | #### 교착 상태 272 | * 둘 이상의 프로세스/스레드가 자원을 점유한 상태에서 서로 다른 프로세스/스레드가 점유하고 있는 자원을 요구하며 `무한정 기다리는` 현상 273 | 274 | #### 발생 조건 275 | -> 4가지 조건을 모두 만족해야 됨
276 | * 상호 배제: 하나의 프로세스/스레드가 자원에 접근할 수 있음 277 | * 비선점: 다른 프로세스/스레드의 자원을 뺏을 수 없음 278 | * 점유와 대기: 자원을 가진 상태에서 다른 자원을 기다림 279 | * 순환 대기: 순환 형태로 자원을 대기 280 | 281 | #### 해결 방법 282 | - 모든 프로세스가 `lock을 잡는 순서를 동일`하게 코딩 283 | - `trylock`을 활용하여 lock을 선점한 프로세스/스레드가 없을 때만 락을 얻으려고 시도하는 방법 284 | * 예방: 4가지 조건 중 1개 이상이 만족하지 않도록 함 285 | * 상호 배제 부정: 여러 프로세스가 공유 자원을 사용하도록 함 286 | * 점유와 대기 부정: 프로세스가 실행되기 전 필요한 모든 자원을 할당 287 | * 비선점 부정: 자원을 점유 중인 프로세스가 다른 자원을 요구할 때, 점유 중인 자원을 반납하고 대기 288 | * 순환 대기 부정: 자원에 고유한 번호를 할당하고, 번호 순서대로 자원을 요구하도록 함 289 | * 회피: 교착상태가 발생하지 않도록 알고리즘 작성 290 | * `은행원 알고리즘`: 어떤 자원을 할당하기 전에 할당 후에도 안정 상태로 있을 수 있는지 검사 후 할당 291 | * 회복: 교착 상태 발생 후, 해당 프로세스를 종료하거나 할당된 자원을 해제 또는 선점하여 해결 292 | * 선점할 경우, `기아 상태`가 발생하지 않도록 해야 함 293 | * 무시: 그냥 무시 294 | 295 |
296 |
297 | 298 | 299 |
300 | 기아 상태(Starvation) 정의와 해결방법 301 |
302 | 303 | #### Starvation 304 | * 여러 프로세스가 부족한 자원을 점유하기 위해 경쟁할 때, `특정 프로세스에 영원히 자원 할당이 되지 않는 경우` 305 | 306 | #### 해결 방법 307 | * 프로세스의 우선 순위 변경 308 | * 요청을 순서대로 처리하는 요청 큐 사용 309 | 310 | #### 식사하는 철학자 문제 311 | 312 | ``` 313 | 5명의 철학자가 원형 식탁에서 식사를 한다.
314 | 젓가락은 다섯개 뿐이며, 철학자는 반드시 두 젓가락이 있어야 식사를 할 수 있다.
315 | 철학자는 반드시 자신의 왼쪽 또는 오른쪽에 있는 젓가락만 사용할 수 있으며, 식사를 마친 후에는 두 젓가락을 모두 내려놓는다. 316 | ``` 317 | 318 | #### 문제 319 | * 모든 사람이 왼쪽의 젓가락을 잡으면 `교착상태` 발생 -> 무한히 대기하다가 `기아상태` 발생 320 | 321 | #### 해결 방법 322 | * 최대 4명의 철학자만 테이블에 동시에 앉을 수 있도록 한다. 323 | * 한 철학자가 젓가락 두 개를 한번에 집을 수 있을 때만 집는다. 324 | * 비대칭 해결안을 사용. 홀수 번호의 철학자는 왼쪽을 먼저 집고 오른쪽을 집는다. 짝수 번호는 오른쪽을 먼저 집고 왼쪽을 집는다. 325 | 326 |
327 |
328 | 329 | 330 |
331 | 동기와 비동기 (Synchronous and Asynchronous) 332 |
333 | 334 | #### 동기 335 | * 요청에 대한 응답이 오면 다음 작업을 요청하는 것 336 | * 함수를 호출한 곳에서 호출된 함수가 결과를 반환할 때까지 대기 -> 작업 완료 여부를 계속 확인 337 | * 구성이 단순하나 멀티태스킹이 불가 338 | 339 | #### 비동기 340 | * 요청에 대한 응답을 기다리지 않고 다음 작업을 요청 341 | * 함수를 호출하는 곳에서 결과를 기다리지 않고 `Callback 함수`가 결과 처리 -> 작업 완료 여부를 확인하지 않음 342 | * 멀티태스킹이 가능하나 복잡도가 증가 (부하 컨트롤, 데이터 일관성 유지 등) 343 | 344 | #### 콜백 함수 345 | * OS가 실행하는 함수 346 | * 특정 이벤트가 발생하면 실행되는 함수 347 | 348 |
349 |
350 | 351 |
352 | 블락킹과 논블락킹 353 |
354 | 355 | #### 블락킹 356 | * `제어권이 호출된 함수로 이동` -> 호출된 함수의 작업이 끝나면 호출한 함수로 제어권 이동 357 | * 요청한 작업을 마칠 때까지 계속 기다림 358 | 359 | #### 논블락킹 360 | * `제어권이 호출한 함수에 있음` -> 작업의 완료 여부와 관계없이 새로운 작업 수행 가능 361 | * 요청한 작업을 즉시 마칠 수 없다면 즉시 리턴함 362 | 363 |
364 |
365 | 366 |
367 | 동기/비동기와 블락킹/논블락킹 368 |
369 | 370 | #### 동기/비동기 371 | * `애플리케이션`에서 자주 다뤄지는 개념이며, `프로세스의 수행 순서 보장`과 관련 372 | * 호출되는 함수의 `작업 완료 여부를 누가 신경쓰느냐가` 관심사 373 | * 비동기는 `콜백`으로 호출된 함수가 완료 여부를 신경쓰고 호출한 함수는 그냥 자기 일을 하다가 콜백을 받으면 됨 374 | 375 | #### 블락킹/논블락킹 376 | * 주로 IO, 멀티 스레딩에서 사용, `프로세스의 유휴 상태`에 대한 개념 377 | * 호출되는 함수가 `바로 return하느냐 마느냐`가 관심사 378 | 379 |
380 |
381 | 382 |
383 | CPU 스케줄링 알고리즘 384 |
385 | 386 | #### SRT (Shortest Remaining Time) 387 | * 선점형 CPU 스케줄링 알고리즘 388 | * `남은 시간이 가장 적은` 프로세스를 실행 389 | 390 | #### Round Robin 391 | * 선점형 CPU 스케줄링 알고리즘 392 | * `Time Slice` 단위로 공평하게 프로세스 실행 393 | * 할당된 시간 내에 끝나지 않으면 다음 프로세스에게 CPU를 양보하고 준비 상태 큐의 가장 뒤로 배치 394 | 395 | #### MLFQ (Multi Level Feedback Queue) 396 | * 선점형 CPU 스케줄링 알고리즘 397 | * 우선 순위 개수만큼 Queue가 있으며 최상위 순위의 Queue부터 실행 후 해당 큐의 할당량이 끝나면 하위 우선 순위 Queue를 실행하는 스케줄링 기법 398 | * 처음 시작은 모든 프로세스가 가장 높은 우선 순위 Queue에 존재하나 할당된 Time Slice를 소진하면 우선 순위를 감소시켜서 우선 순위 결정 399 | * `Aging`: 일정 주기마다 모든 작업을 가장 높은 우선 순위 큐로 이동시켜서 Starvation 방지 400 | 401 |
402 |
403 | 404 |
405 | 메모리 계층 구조 406 |
407 | 408 | ![image](https://user-images.githubusercontent.com/38535571/230782257-ab9c1771-a53f-420f-a881-7a725b14a194.png) 409 | 410 | * 레지스터: CPU 안에 있는 작은 메모리로 속도가 매우 빠르나 휘발성이 높고 용량이 매우 작음 411 | * 캐시: L1, L2, L3 캐시를 지칭하는데 레지스터 보다 정도가 낮지만 속도가 매우 빠르나 휘발성이 높고 용량이 매우 작음 412 | * 주기억장치: RAM을 지칭하는데 일반적인 속도와 휘빌성 그리고 적당한 용량을 가짐 413 | * 보조기억장치: HDD, SSD를 지칭하는데 비휘발성이고 속도가 느리고 용량이 많음 414 | 415 | 416 |
417 |
418 | 419 |
420 | 캐시 매핑 421 |
422 | 423 | #### 캐시 매핑 424 | 캐시가 히트되기 위해 매핑하는 방법 425 | 426 | #### 캐시 매핑 분류 427 | * 직접 매핑: 메모리가 1~100이 있고 캐시가 1~10이 있다면 1:1~10, 2:1~20 같은 방식으로 매핑하는 것으로 처리가 빠르지만 충돌이 잦음 428 | * 연관 매핑: 순서를 일치시키지 않고 관련 있는 캐시와 메모리를 매핑하는 방법으로 충돌지 적지만 모든 블록을 탐색해야하여 속도가 느림 429 | * 집합 연관 매핑: 메모리가 1~100이 있고 캐시 1~10이 있다면 캐시 1~5에는 메모리 1~50의 데이터를 무작위로 저장하는 것과 같은 방식으로 매핑하는 것으로 직접 매핑가 연관 매핑을 합쳐서 순서를 일치시키지만 집합을 둬서 저장하며 블록화하여 검색이 좀 더 효율적 430 | 431 |
432 |
433 | 434 |
435 | 캐시의 지역성 436 |
437 | 438 | * 시간 지역성: `최근`에 참조된 주소가 다시 참조되는 특성 (순환, 재귀) 439 | * 공간 지역성: 참조된 주소와 `인접한` 주소가 다시 참조되는 특성 (배열) 440 | 441 |
442 |
443 | 444 | 445 |
446 | 가상 메모리 447 |
448 | 449 | ![image](https://user-images.githubusercontent.com/38535571/230782274-ae946b47-931b-4712-9254-873c870292eb.png) 450 | 451 | #### 가상 메모리 452 | * `물리 메모리 크기의 한계를 극복`하기 위해 나온 기술로 메모리가 실제 메모리보다 많아 보이게 하는 기술 453 | * 프로그램에 실제 메모리 주소가 아닌 `가상의 메모리 주소를 주는 방식`으로 프로그램 별로 사용 중인 메모리보다 큰 메모리를 사용하는 듯한 환상을 주는 기법 454 | * `MMU(Memory Management Unit)`는 가상 메모리 주소를 물리 주소로 변환 455 | 456 | #### 가상 메모리 사용 시 장점 457 | * 실제 프로그램 전체를 적재하여 사용하지 않고 일부분만 적재하기 때문에 메모리 제약을 극복 458 | * 메모리의 실제 주소를 사용하지 않으므로 보안 상의 장점이 존재 459 | 460 |
461 |
462 | 463 |
464 | 세그멘테이션 465 |
466 | 467 | * 메모리에 불연속적으로 할당하는 방법 중 하나로 프로세스를 서로 다른 크기의 논리적 단위인 `세그먼트`로 나누어 메모리에 배치하는 것 468 | * 메모리를 세그먼트로 나누고 `세그먼트 테이블`에 각 세그먼트의 `시작(base) 주소`와 `크기(limit)` 정보를 운용하여 가상 메모리를 관리하는 기법 469 | * 작은 메모리가 중간 중간 존재하여 총 메모리는 충분하지만 실제로는 할당할 수 없는 상황인 `외부 단편화`가 발생할 수 있음 470 | 471 |
472 |
473 | 474 |
475 | 페이징 476 |
477 | 478 | * 메모리에 불연속적으로 할당하는 방법 중 하나로 프로세스를 `일정 크기인 페이지`로 잘라서 가상 메모리에 적재하고 `페이지 테이블`을 이용하여 프레임으로 변환하여 가상 메모리를 관리하는 기법 479 | * 현대 운영체제에서 사용되는 메모리 할당 기법 480 | * CPU가 가상 주소 접근 시 MMU가 페이지 테이블의 `시작(base) 주소`에 접근해서 물리주소 가져옴 481 | * 메모리를 할당할 때 프로세스가 필요한 양보다 더 큰 메모리가 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비 되는 현상인 `내부 단편화`가 발생할 수 있음 482 | * 페이지: `가상 메모리`를 최소 단위로 쪼개어 만든 `일정한` 크기의 블럭 483 | * 프레임: `물리 메모리`에 페이지 크기와 같은 블럭으로 나눈 블럭 484 | 485 |
486 |
487 | 488 |
489 | 페이지 테이블, TLB (Translation Lookaside Buffer) 490 |
491 | 492 | #### 요약 493 | * 가상 주소로 물리 주소에 접근할 때, `TLB -> 페이지 테이블 -> Disk` 순으로 접근 494 | 495 | #### 과정 496 | * MMU는 TLB 캐시를 저장해 가상주소가 물리 주소로 변환되어야할 때, `TLB`에서 먼저 검색 497 | * 해당 주소가 있다면: `TLB Hit` -> 물리 주소가 반환되고 메모리에 접근 498 | * 해당 주소가 없다면: `TLB Miss` -> `페이지 테이블`에서 페이지와 프레임의 맵핑 탐색 499 | * 해당 주소가 있다면: `페이지 테이블 Hit` -> 이 값을 다시 TLB에 쓰고 물리 주소로 변환 후 메모리에 접근 500 | * 해당 주소가 없다면: `Page Fault` -> `Disk`에서 찾아 이 값을 페이지 테이블과 TLB에 쓰고 물리 주소로 메모리에 접근 501 | 502 |
503 |
504 | 505 |
506 | 페이지 교체 알고리즘 507 |
508 | 509 | #### FIFO 510 | * 들어온 페이지 `순서대로` 페이지를 교체하는 알고리즘 511 | * `Belady의 모순` 발생: 페이지 프레임의 개수를 늘리면 Page Fault 발생이 감소할 것 같으나, 실제로는 실패가 증가할 수도 있음 512 | 513 | #### LRU (Least-Recently-Used) 514 | * `가장 오랫동안 사용되지 않은` 페이지를 선택하여 교체하는 알고리즘 515 | 516 | #### LFU (Least-Frequently-Used) 517 | * `참조 횟수가 가장 적은 페이지`를 교체하는 알고리즘 518 | 519 |
520 |
521 | 522 |
523 | 컴퓨터가 부팅되는 과정 524 |
525 | 526 | * 처음에 부팅이 되면 `BIOS`가 실행 될 수 있도록 `메모리의 0번지에는 ROM`이 올라와있고, `CPU는 0번지를 읽어` 자동으로 ROM의 BIOS가 실행 527 | * `BIOS는 하드디스크의 0번지 부터 한 섹터를 읽어와 거기에 있는 부트스트랩 코드를 실행` 528 | * 부트스트랩이 `부트로더`(bootcamp, grub)를 실행시키고 그 다음 커널이 로드 529 | 530 |
531 |
532 | 533 |
534 | 심볼릭 링크와 하드 링크의 차이 535 |
536 | 537 | * 심볼릭 링크(소프트 링크): 원본 파일의 이름을 가리키는 링크, 원본 파일이 사라지면 역할 수행X 538 | * 하드 링크: 원본 파일의 이름을 가리키는 링크, 사본을 생성, 원본파일이 사라져도 원본과 동일한 내용의 파일을 가질 수 있음을 의미 539 | 540 |
541 |
542 | 543 |
544 | 컴파일러와 인터프리터의 차이 545 |
546 | 547 | #### 컴파일러 548 | * 프로그램 `전체`를 한 번에 번역 549 | * 목적 프로그램 생성: 목적 프로그램(기계어)으로 번역 -> 링킹 -> 실행 가능한 실행파일(어셈블리, 바이너리 파일) 생성 550 | * 번역 속도 느림, 실행 속도 빠름 551 | * C, Java 552 | 553 | #### 인터프리터 554 | * 프로그램을 `한 줄씩` 번역 555 | * 번역과 동시에 프로그램 실행 556 | * 번역 속도 빠름, 실행 속도 느림 557 | * Python 558 | 559 |
560 |
561 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Developer Interview 2 | 개발자 인터뷰 질문에 관련된 `팁과 최소 개념`입니다. 모든 내용을 레포에 자세하게 담기엔 어려워서 내용을 더 학습하고 싶다면 관련 주제를 검색하여 공부하는 것을 추천합니다. 레포의 내용은 기본적인 CS 지식 정리와 실제 인터뷰 경험 그리고 여러 책과 자료들을 참고하여 만들었습니다. 기본 CS 지식은 동일하나 제 직무가 JVM 기반의 `백앤드, 빅데이터 플랫폼, 클라우드, SRE` 관련 직무이므로 이를 감안하시길 바랍니다. 잘못된 내용이나 부족한 내용 또는 추가했으면 하는 내용이 있다면 [Issues](https://github.com/yoonje/developer-interview/issues)에 남겨주세요. 양식을 맞춰서 [PR](https://github.com/yoonje/developer-interview/pulls) 해주시면 더욱 좋습니다. 3 | 4 | ## 참고 문서 5 | ##### GitHub 6 | - https://github.com/tvandame/back-end-developer-interview-questions/blob/master/Translations/Korean/README_KR.md 7 | - https://github.com/WooVictory/Ready-For-Tech-Interview 8 | - https://github.com/qkraudghgh/coding-interview 9 | - https://github.com/WeareSoft/tech-interview 10 | - https://github.com/huisam/interview 11 | - https://github.com/JaeYeopHan/Interview_Question_for_Beginner 12 | - https://github.com/gyoogle/tech-interview-for-developer 13 | - https://github.com/jwasham/coding-interview-university 14 | - https://github.com/donnemartin/system-design-primer 15 | 16 | ##### 도서 17 | - [면접을 위한 CS 전공지식 노트](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=292815727) 18 | - [프로그래밍 면접 이렇게 준비한다](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=195800711) 19 | - [코딩 인터뷰 완전 분석](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=115116545) 20 | - [가상 면접 사례로 배우는 대규모 시스템 설계 기초](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=276041776) 21 | - [자바 코딩 인터뷰 완벽 가이드](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=299393634) 22 | - [262가지 문제로 정복하는 코딩 인터뷰 in Java](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=279822364) 23 | 24 | ## Table of Content 25 | - [Algorithm](./Algorithm/README.md) 26 | - [Database](./Database/README.md) 27 | - [Datastructure](./Datastructure/README.md) 28 | - [System Design](./SystemDesign/README.md) 29 | - [Design Pattern](./DesignPattern/README.md) 30 | - [Network](./Network/README.md) 31 | - [OOP](./OOP/README.md) 32 | - [OS](./OS/README.md) 33 | - [Java](./Java/README.md) 34 | - [Spring](./Spring/README.md) 35 | - [Web](./Web/README.md) 36 | - [Live Coding](./LiveCoding/README.md) 37 | - [Etc](./Etc/README.md) 38 | 39 | ## Template 40 | ```yml 41 |
42 | 제목 43 |
44 | 내용 45 |
46 |
47 | ``` 48 | -------------------------------------------------------------------------------- /Spring/README.md: -------------------------------------------------------------------------------- 1 | # Spring 2 | 3 |
4 | 5 |
6 | 스프링과 스프링 부트 7 |
8 | 9 | #### 스프링 10 | * 자바의 `오픈 소스 애플리케이션 프레임워크` 11 | * 객체를 관리할 수 있는 컨테이너 제공 12 | * IOC, DI, AOP를 지원 13 | 14 | #### 스프링 부트 15 | * 스프링 기반의 애플리케이션을 간편하게 설정할 수 있는 도구 16 | * 내장 서버: `Embeded Tomcat`이 포함되어 있어 Tomcat을 따로 설치/관리할 필요가 없음 17 | * Starter를 이용한 의존성 자동화 18 | 19 |
20 |
21 | 22 | 23 |
24 | Maven과 Gradle 25 |
26 | 27 | * 빌드 관리 도구: 라이브러리, 종속성 정보 등을 설정 파일을 통해 자동으로 다운로드해 간편히 관리해주는 도구 28 | 29 | #### Maven 30 | * Java용 프로젝트 관리 도구 31 | * Apache Ant의 단점을 해소하기 위해 사용 32 | * 빌드 중인 프로젝트, 라이브러리 등 종속 관계를 `pom.xml`에 명시 33 | * Project Object Model 34 | 35 | #### Gradle 36 | * Java, C/C++, Python 등을 지원 37 | * Apache Maven과 Apache Ant의 장점을 합친 빌드 관리 도구 (완전한 오픈 소스) 38 | * `Build.gradle` 사용: JVM 위에서 동작하는 `Groovy` 언어를 사용 (XML보다 간결) 39 | 40 | #### 차이점 41 | * Gradle은 `Incremental Build`를 허용해 `빌드 시간이 단축` 42 | * 이미 업데이트된 Task는 빌드가 진행되지 않아 시간 단축 가능 43 | * Maven 보다 빠름 44 | * 빌드 접근 방식 차이: Gradle은 `작업 의존성 그래프`에 기반, Maven은 `고정적이고 선형적인 단계의 모델`에 기반 45 | * Gradle은 `Build Cache` 사용 46 | * 2개 이상의 빌드가 있을 경우, 하나의 빌드에서 사용된 파일이 다른 빌드에서 사용되면, 빌드 캐시를 이용해 이전 결과물을 다른 빌드에 사용 가능 47 | 48 |
49 |
50 | 51 | 52 |
53 | DI 54 |
55 | 56 | * Dependency Injection, 의존 관계 주입 57 | * 객체 간의 의존 관계를 미리 설정해 두면 스프링 컨테이너가 의존관계를 자동으로 연결 58 | * 의존하는 객체를 직접 생성하거나 검색해서 가져올 필요가 없어 `결합도`가 낮아짐 59 | 60 | #### 참고 61 | * 객체들의 `의존성(결합도)을 줄이기 위해` 사용되는 스프링의 IOC 컨테이너의 구체적인 구현 방식 62 | * 개발 코드에서 객체를 생성하는 것이 아니라, 데이터 주입만 담당하는 별도의 공간에서 객체를 생성하고 데이터간의 의존성을 주입해 개발 코드에서 가져다 씀 63 | * 애플리케이션 실행 시점에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달 64 | * 재사용성 향상, 팩토리 패턴과 유사 65 | * 방법 3가지: 생성자에 `@Autowired` 추가, 필드 주입, setter 주입(setter에 `@Autowired` 추가) 66 | 67 |
68 |
69 | 70 | 71 |
72 | IoC 73 |
74 | 75 | * Inversion of Control, 제어의 역전 76 | * 제어권이 사용자에게 있지 않고 프레임워크에 있는 것 77 | * 메소드나 객체의 호출을 개발자가 결정하는 것이 아니라, `외부에서 결정` 78 | * 객체의 생성부터 소멸까지 개발자가 아닌 `컨테이너`가 관리하는 것 79 | 80 |
81 |
82 | 83 | 84 |
85 | AOP 86 |
87 | 88 | * Aspect Oriented Programming, 관점 지향 프로그래밍 89 | * `공통 관심 사항(Cross-Cutting Concern)`과 핵심 관심 사항(Core Concern)을 분리하는 것 90 | * 특정 로직(로그, 성능테스트 등)을 모든 메소드에 적용하고 싶을 때, 모든 메소드에 일일이 로직을 추가하는 것이 아니라, 로직을 만들어서 모든 메소드에 적용 91 | * 비지니스 로직의 앞/뒤에 공통 관심 사항을 수행해 `중복 코드를 줄이는 것` 92 | 93 |
94 |
95 | 96 | 97 |
98 | 스프링 컨테이너와 스프링 빈 99 |
100 | 101 | * 자바 객체의 생명 주기(생성 ~ 소멸)를 관리하는 컨테이너 102 | * 스프링 컨테이너에는 `BeanFactory`, `ApplicationContext` 인터페이스가 있음 103 | * 자바 객체를 스프링 빈이라고 함 104 | 105 | #### 참고 106 | * `AppConfig` 클래스 같은 것이 스프링 컨테이너 -> `@Configuration` 사용 107 | * `AppConfig` 내에서 `@Bean`이 붙은 것이 스프링 빈 108 | 109 |
110 |
111 | 112 | 113 |
114 | ApplicationContext 115 |
116 | 117 | * 스프링 컨테이너 118 | * `BeanFactory` 인터페이스의 하위 인터페이스 119 | * `BeanFactory`는 스프링 컨테이너의 최상위 인터페이스로 `ApplicationContext`는 `BeanFactory`에 부가 기능을 추가한 것 120 | 121 |
122 |
123 | 124 | 125 |
126 | 스프링 빈 주입 방법 127 |
128 | 129 | #### 스프링 빈 주입 방법 130 | 131 | * 필드 주입: 필드에 `@Autowired` 어노테이션 사용 132 | * 생성자 주입: 생성자에서 파라미터로 의존성을 주입, 생성자가 1개라면 `@Autowired` 어노테이션이 필수적이지 않음 133 | 134 | #### 생성자 주입을 사용하는 것이 좋음 135 | * `순환 참조` 방지 가능 136 | * 생성자 주입: 생성자로 객체를 생성하는 시점에 생성자의 인자에 사용되는 빈을 찾거나 생성 -> 빈의 생성자를 호출 137 | * 그 외: 빈을 먼저 생성 -> 어노테이션이 붙은 필드에 해당하는 빈을 찾아서 주입 / Setter의 객체를 호출해 주입 -> 객체가 실제로 사용되기 전까지는 에러가 발생하지 않음 138 | * `final` 키워드로 불변하는 객체를 생성할 수 있음 139 | * 런타임에 중에 객체가 변하는 것을 막아 불변성을 유지할 수 있어 오류를 사전에 방지할 수 있음 140 | 141 |
142 |
143 | 144 | 145 |
146 | @Bean 과 @Component의 차이 147 |
148 | 149 | #### @Bean 150 | * 메소드 레벨에서 선언 151 | * 반환되는 객체(인스턴스)를 개발자가 수동으로 등록 152 | 153 | #### @Component 154 | * 클래스 레벨에서 선언 155 | * 스프링이 런타임시에 컴포넌트스캔을 하여 자동으로 빈을 등록 156 | 157 |
158 |
159 | 160 | 161 | 162 |
163 | 스프링 빈 스코프 164 |
165 | 166 | * 빈이 관리되는 범위 167 | 168 | ```java 169 | @Scope("singletone") 170 | ``` 171 | 172 | #### Singleton 173 | * Default Scope 174 | * 이유: 대규모 트래픽을 처리할 수 있도록 하기 위해서, 성능을 위해서 175 | * 스프링 컨테이너의 시작과 종료까지 1개의 객체로 유지됨 176 | 177 | 178 | #### Prototype 179 | * Bean 객체를 요청할 때마다 새로운 객체 생성 180 | * 프로토타입을 받은 클라이언트가 객체를 관리 181 | 182 | #### Web (MVC Wep 앱에서만 사용) 183 | * Request: HTTP 요청별로 객체화, 요청이 끝나면 소멸 184 | * Session: HTTP 세션별로 객체화, 세션이 끝나면 소멸 185 | * Application: Web의 `Servlet Context`와 동일한 생명주기를 가짐 186 | * Websocket: web socket과 동일한 생명주기를 가짐 187 | 188 |
189 |
190 | 191 | 192 |
193 | 스프링 MVC 194 |
195 | 196 | * Model: 비지니스 로직를 처리, DB와 상호작용하는 모듈 197 | * View: Client에게 보여지는 화면을 반환하는 모듈 198 | * Controller: 모델과 뷰 사이의 정보 교환, Client 요청이 들어왔을 때, 어떤 로직을 실행할 것인지 제어하는 모듈 199 | 200 |
201 |
202 | 203 | 204 |
205 | 스프링 MVC 과정 206 |
207 | 208 | 1. 클라이언트가 서버에 요청을 보내면 `DispatcherServlet`에 요청이 전달
209 | * DispatcherServlet: Front Controller 210 | 2. `DispatcherServlet`은 요청된 `URL`을 `HandlerMapping`에게 전달, ` HandlerMapping`은 호출해야 할 `Controller` 객체를 리턴
211 | 3. DispatcherServlet이 `HandlerAdapter` 객체에게 요청을 위임하고 `HandlerAdapter`는 `컨트롤러의 메소드를 실행(호출)`하여 `ModelAndView` 객체로 반환
212 | 4. DispatcherServlet은 `ViewResolver`를 이용해 `View` 객체를 얻음
213 | * `ModelAndView` 객체의 View이름으로 객체를 찾음, 없다면 생성하여 반환 214 | 5. DispatcherServlet은 ViewResolver가 리턴한 View객체를 이용해 사용자에게 화면 표시(응답 결과 표시) 215 | 216 | #### 참고 217 | *`HandlerMapping`, `HandlerAdapter`, `ViewResolver`: Spring Bean 218 | * HandlerMapping: `@Controller`로 선언되었거나 `HttpRequestHandler` 인터페이스를 구현한 클래스를 찾음 219 | * ModelAndView: 응답할 View 이름과 View에 전달할 데이터 220 | 221 |
222 |
223 | 224 | 225 |
226 | MVC 1과 MVC 2의 차이 227 |
228 | 229 | #### MVC 1 230 | * `JSP` 페이지에서 View, Controller 역할 담당 (로직 처리) 231 | * 구조 단순 232 | * JSP 내에서 html과 자바 코드가 함께 사용되어 복잡하고 유지보수가 어려움 233 | #### MVC 2 234 | * Model, View, Controller로 모듈화됨 235 | * JSP는 Client에게 보여지는 `View`만 담당 (로직 처리 없음) 236 | * 구조가 복잡하나 유지보수가 용이함 237 | 238 | #### 참고 239 | * Spring MVC는 `MVC2`로 설계되어 있음 240 | 241 |
242 |
243 | 244 | 245 |
246 | Servlet 247 |
248 | 249 | * 클라이언트의 요청을 처리해 결과 반환, 웹 페이지를 동적으로 생성하기 위한 서버측 프로그램 250 | * Spring MVC에서 `Controller` 역할 수행 251 | 252 |
253 |
254 | 255 | 256 |
257 | DispatcherServlet 258 |
259 | 260 | * 서버로 들어오는 요청을 처리하는 `Front Controller` 261 | * 웹 요청의 진입점, 요청을 처리하여 결과를 응답 262 | 263 | #### 디스패처 서블릿으로 인한 web.xml 역할 축소 264 | * 기존에는 모든 서블릿에 대해 URL 매핑을 활용하기 위해 web.xml에 등록이 필수 265 | * 디스패처 서블릿이 요청을 처리하면서 작업이 편리 266 | 267 |
268 |
269 | 270 | 271 |
272 | 필터와 인터셉터 차이 273 |
274 | 275 | * `실행되는 시점`의 차이 276 | 277 | #### 필터 278 | * 웹 애플리케이션에 등록 (스프링 Context 외부에 존재) 279 | * 서블릿 필터: `DispatcherServlet` `이전`에 실행 -> 자원의 앞단에서 요청 내용 변경/검증 수행 280 | 281 | #### 인터셉터 282 | * 스프링 Context에 등록 283 | * `DistpatcherServlet`이 `컨트롤러`를 호출하기 전(요청), 후(응답)에 동작 -> Controller에 관한 요청과 응답 처리 284 | 285 |
286 |
287 | 288 | 289 |
290 | Self-invocation 문제 291 |
292 | 293 | * 스프링 컴포넌트에 있는 AOP 어노테이션은 `스프링 프록시`를 기반으로 동작하기 때문에 내부 호출을 할 때는 프록시가 적용되지 않음 294 | 295 | 296 |
297 |
298 | 299 | 300 |
301 | ORM (Object Relational Mapping) 302 |
303 | 304 | * 관계형 DB를 OOP 언어로 변환하는 기술 305 | * `객체` 클래스를 `RDB 테이블`에 자동으로 연결하는 것 -> SQL 없이 간접적으로 DB 조작 가능 306 | * 비지니스 로직에 집중할 수 있음, DBMS 종속성 하락 307 | * 프로그램의 복잡성이 커지면 난이도 증가, 잘못될 경우 문제 발생할 가능성 있음 308 | 309 |
310 |
311 | 312 | 313 |
314 | Java Persistence API 정의 315 |
316 | 317 | * ORM을 위해 자바에서 제공하는 API 318 | * 자바 ORM 기술에 대한 API 표준 명세 319 | * 자바 애플리케이션에서 `관계형 DB`를 사용하는 방식을 정의한 `인터페이스` 320 | * `EntityManager`를 통해 `CRUD` 처리 321 | 322 |
323 |
324 | 325 | 326 |
327 | JPA에서 Entity를 설계할 때 주의점 328 |
329 | 330 | * `Setter`를 사용하지 않음 331 | * 모든 연관 관계는 `지연로딩(LAZY)`으로 설정 332 | * 즉시로딩(EAGER)를 사용 할 경우, 어떤 SQL이 나갈지 추적하기 어려움 333 | * 컬렉션은 필드에서 바로 초기화 334 | 335 | #### 참고 336 | * `@ManyToOne`과 같은 연관 관계가 있을 경우 337 | * 지연로딩: 연관 테이블은 조회하지 않고, 연관 관계가 실제로 사용되는 시점에 조회 338 | * 즉시로딩: 연관 테이블까지 바로 조회
339 |   -> 많은 데이터가 조회될 수 있음 340 | 341 |
342 |
343 | 344 | 345 |
346 | JPA 영속성 컨텍스트 347 |
348 | 349 | * `엔티티를 영구 저장`하는 환경 350 | * 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 환경 351 | * 영속성 컨텍스트의 생명 주기는 트랜잭션과 동일 352 | 353 | #### 생명주기 354 | * 비영속: 영속성 컨텍스트와 전혀 관계가 없는 상태, 객체를 생성한 상태 355 | * 영속: 엔티티가 영속성 컨텍스트에 의해 관리되는 상태 356 | * 준영속: 영속성 컨텍스트에 저장되었다가 분리된 상태 357 | * 삭제: 엔티티 객체를 영속성 컨텍스트와 DB에서 삭제 358 | 359 | #### 1차 캐시 360 | * 영속성 컨텍스트에서 엔티티를 저장하는 장소 361 | * 같은 엔티티가 있으면 동일한 객체임을 보장 362 | 363 | #### 2차 캐시 364 | * 애플리케이션 범위의 캐시, 공유 캐시 365 | * 애플리케이션이 종료될때까지 캐시 유지 366 | * `동시성`을 극대화 하기 위해 캐시한 객체가 아닌 `복사본`을 반환 367 | * 영속성 컨텍스트가 다르면 동일한 객체임을 보장하지 않음 368 | 369 |
370 |
371 | 372 | 373 |
374 | JPA Fetch 종류 375 |
376 | 377 | * 즉시 로딩: 엔티티를 조회할 때, 연관된 엔티티도 `함께` DB를 조회 378 | * 지연 로딩: 엔티티를 조회할 때, 연관된 엔티티는 조회하지 않고 `프록시 객체`로 넣어두었다가 엔티티가 실제로 `사용`될 때 조회 379 | 380 | #### 프록시 381 | * 실제 엔티티 대신에 사용되는 객체, 원본 엔티티를 `상속`받은 객체 382 | 383 |
384 |
385 | 386 | 387 |
388 | JPA N+1 문제 389 |
390 | 391 | * 조회 시, 1개의 쿼리를 생각하고 설계했으나 예상하지 못했던 쿼리 N개 더 발생하는 문제 392 | * `연관 관계`에 의해 다른 객체가 함께 조회되어 N+1 문제가 발생함 393 | 394 | #### 원인 395 | * 즉시 로딩 시에, 전체 데이터를 조회하고 Eager가 감지되어 N개의 쿼리가 추가로 발생 396 | * 지연 로딩 시에, 전체 데이터를 조회한 후, 연관된 객체가 사용될 때 N개 쿼리가 발생 397 | 398 | #### 해결 방법 399 | * Fetch Join 사용: 연관된 엔티티나 컬렉션을 한 번에 함께 조회하는 역할 400 | * @EntityGraph 사용 401 | * @BatchSize 사용:` where 절의 in 조건`으로 미리 지정된 사이즈 만큼만 조회하여 1개 쿼리로 처리 가능 402 | * @Fetch 사용: `where 절의 in 조건`으로 조회해 1개 쿼리로 처리 가능 (BatchSize 무한대와 동일) 403 | 404 |
405 |
406 | 407 | 408 | 409 |
410 | JPA에서 Entity Id에 Long을 사용해야 되는 이유 411 |
412 | 413 | * Wrapper Type인 Long을 사용해야 Null을 사용할 수 있음 414 | * 하이버네이트 공식 문서에도 Nullable한 값을 사용하라고 권장 415 | 416 |
417 |
418 | 419 | 420 |
421 | JPA에서 스프링에서 다대다 관계가 좋지 않은 이유 422 |
423 | 424 | * 다대다의 경우, 정규화를 통해 `중간 테이블`을 생성해야 함 425 | * 중간 테이블로 `일대다` + `다대일` 형태로 변형해야 함 426 | * JPA에서 `@ManyToMany` 연관 관계를 사용할 경우, 하이버네이트가 중간 테이블을 알아서 만들어서 처리 427 | * 관계 설정에 필수적으로 필요한 정보만 담기고 비지니스 로직에 필요한 정보는 담기지 않음 428 | * 실무에서는 사용하지 않는 것을 권장 429 | * 다대다 관계를 사용하고 싶은 경우라면 중간 테이블에 대한 클래스를 직접 만들어서 `@OneToMany`, `@ManyToOne`의 조합을 만들어 사용해야 함 430 | 431 | #### 정리 432 | * 중간 테이블에는 매핑정보만 들어가고 추가 데이터를 넣는 것이 불가능 433 | * 중간 테이블이 숨겨져 있기 때문에 쿼리가 예상하지 못하는 형태로 발생 가능 434 | * 실무 비즈니스는 복잡해서 ManyToMany로 풀 수있는게 거의 없음 435 | 436 |
437 |
438 | 439 | 440 |
441 | Hibernate 442 |
443 | 444 | * `JPA의 구현체`, 인터페이스를 직접 구현한 `라이브러리` 445 | * SQL문을 직접 작성하지 않고 `메소드 호출`만으로 쿼리 수행이 가능해 생산성 향상 446 | * 생산성, 유지보수, 비종속성 447 | 448 |
449 |
450 | 451 | 452 |
453 | ORM, JPA, Hibernate 장단점 454 |
455 | 456 | #### 장점 457 | * 비지니스 로직에 집중 가능, 객체 중심 개발 가능 458 | * 메소드 호출만으로 DB 조작 -> 생산성 향상, 유지보수 쉬움 459 | * DBMS 의존성 하락 460 | 461 | #### 단점 462 | * 직접 SQL을 호출하는 것보다는 성능이 떨어짐 463 | * 복잡한 쿼리는 메소드로 처리가 어려움 464 | 465 |
466 |
467 | 468 | 469 |
470 | Spring Data JPA 471 |
472 | 473 | * JPA를 편리하게 사용할 수 있도록 스프링에서 제공하는 프로젝트 474 | * CRUD 처리를 위한 공통 `인터페이스` 제공 475 | 476 |
477 |
478 | 479 | 480 |
481 | Mybatis 482 |
483 | 484 | #### 정의 485 | * 자바의 관계형 데이터베이스 프로그래밍을 쉽게 할 수 있도록 도와주는 개발 프레임워크 486 | * JDBC를 통해 DB에 접근하는 작업을 캡슐화, SQL 쿼리 매핑 487 | #### 사용 이유 488 | * 프로그램의 SQL 쿼리를 한 파일로 구성하여 코드와 SQL을 분리할 수 있어 사용 489 | 490 |
491 |
-------------------------------------------------------------------------------- /SystemDesign/README.md: -------------------------------------------------------------------------------- 1 | # Design 2 | 3 | ## 영화관 좌석 예매 프로그램을 만들려고 한다. 해당 좌석에 대해 어떤 자료구조를 사용할 것인가? 4 | * 영화관 자석 예매 시 좌석에 대해 동시적인 접근이 이뤄지므로 동기화 처리가 이뤄진 자료구조를 사용해야한다. 5 | * 탐색 관점에 있어서는 Array가 빠를 것 같다. 6 | 7 | ## 은행에서 송금을 하는 과정이 3단계로 되어 있는데 3단계에서 오류가 났다. 어떻게 해야하는가? 8 | * ACID의 A의 원칙에 따라 전체를 Rollback 해야한다. 9 | 10 | ## DB 관점에서 제한된 리소스로 인해 트래픽의 요청이 많아 대해서 어려움을 겪고 있을때 해결할 수 있는 방법은 무엇인가? 11 | * 커넥션 풀을 이용하거나 메모리 캐시 DB를 이용한다. 12 | 13 | ## 서버 인스턴스를 여러 개 돌릴 때 어떤 걸 고려해야되나? 14 | * 공유 자원에 대한 쓰기가 있을 경우 동기화가 이뤄져야한다. -------------------------------------------------------------------------------- /Web/README.md: -------------------------------------------------------------------------------- 1 | # Web 2 | 3 |
4 | 5 | 6 |
7 | HTTP 특징 8 |
9 | 10 | #### Connectionless 11 | * 클라이언트에서 서버에 요청을 보내면 서버는 클라이언트에 응답을 하고 접속을 끊음 12 | 13 | #### Stateless 14 | * HTTP 통신은 요청에 응답하고 접속을 끊기 때문에 클라이언트의 상태정보를 저장하지 않음 15 | 16 |
17 |
18 | 19 | 20 |
21 | HTTP 0.9, 1, 1.1, 2, 3의 차이 22 |
23 | 24 | #### HTTP 0.9 25 | * HTTP 헤더가 없음, 상태 코드 없음 26 | * `GET`만 가능 27 | * `HTML 파일`만 전송 가능 28 | * 하나의 연결당 1요청 1응답 -> 성능 저하, 서버 부하 29 | 30 | #### HTTP 1.0 31 | * HTTP 헤더가 생김, 상태 코드 생김 32 | * `content-type`을 통해 HTML이 아닌 데이터도 전달 가능 33 | * `Short Connection`: 하나의 연결에 1요청 1응답 -> 성능 저하, 서버 부하 34 | * 매 요청마다 TCP 세션을 설정(3-way)하고 종료(4-way)하는 과정 진행 35 | 36 | #### HTTP 1.1 37 | * `Persistent Connection`: 지정한 Timeout 동안 커넥션을 닫지 않음 38 | * TCP 세션을 설정(3-way) -> N요청/응답 -> 종료(4-way) 39 | * `connection : keep-alive` 헤더를 응답으로 전송 40 | * `파이프라이닝` 41 | * 1.0: 1요청 -> 1응답, 2요청 -> 2응답, 3요청 -> 3응답 42 | * 1.1: 1, 2, 3요청 -> 1, 2, 3응답 43 | * 하나의 커넥션에서 응답을 기다리지 않고 순차적인 여러 요청을 연속으로 전송, 요청 순서에 맞춰 응답을 받음 -> RTT(Round Trip TIme) 감소 44 | * HOL(Head of Line) Blocking: 파이프라이닝의 문제점 -> 먼저 받은 요청이 Block되면 다음 요청도 처리 불가 45 | * 헤더의 중복: 파이프라이닝에서 전송되는 요청들의 헤더/쿠키는 많은 부분이 중복 -> 자원 낭비 46 | 47 | #### HTTP 2.0 48 | * 메시지 전송 방식 변화 49 | * 바이너리 프레이밍 계층 사용: 데이터는 `바이너리`로 인코딩해서 전송, 데이터를 `프레임` 단위로 나눔 50 | * 전송속도 향상, 오류 발생 가능성 하락 51 | * `멀티플렉싱`을 통해 HOL(Head of Line) Blocking 해결 -> 레이턴시 감소 52 | * 하나의 커넥션에서 여러 스트림 교환 가능 53 | * 순서를 상관하지 않고 전송, 순서는 스트림 우선순위로 수신측에서 재조합 54 | * `HTTP 헤더 압축`: 헤더 크기 감축 (Huffman Coding) -> 오버헤드 감소 55 | * Server Push: 클라이언트가 요청 하지 않은 JavaScript, CSS, Font, 이미지 파일 등과 같이 필요하게 될 특정 파일들을 서버에서 HTTP 응답에 함께 전송 56 | 57 | #### HTTP 3 (QUIC) 58 | * `UDP 기반` 으로 변화 59 | * TCP는 신뢰성을 확보하지만 지연을 줄이기 힘듦 60 | * UDP는 공간이 많아 TCP의 지연을 줄이면서 TCP만큼 신뢰성을 보장하도록 개발 61 | * `HTTPS` 필수 62 | 63 | #### 참고 64 | * HTTP 2.0 65 | * 스트림 > 메시지 > 프레임 66 | * 프레임: 통신의 최소 단위 67 | * 헤더 프레임: HTTP 헤더 저장, Data 프레임: HTTP 응답 저장 68 | * 메시지: 다수의 프레임, 요청/응답의 단위 69 | * 스트림: 양방향 통신을 통해 전달되는 한 개 이상의 메시지 70 | * HTTP 3.0 71 | * 전송 속도 향상: 첫 연결 설정에서 필요한 정보와 함께 데이터 전송 -> 연결 성공시 설정을 캐싱하여 다음 연결 때 바로 성립 가능 72 | * Connection UUID: 고유한 식별자로 서버와 연결 -> 커넥션 재수립 필요X 73 | * 독립 스트림 -> 향상된 멀티플렉싱 74 | * 헤더 압축(QPACK) 75 | 76 |
77 |
78 | 79 | 80 |
81 | HTTP 상태코드 82 |
83 | 84 | * 1XX: 정보 응답으로 서버는 요청을 받았고 클라이언트는 작업을 계속 진행하라는 의미 85 | * 2xx: 요청과 응답에 성공 86 | * 3xx: 리다이렉션 응답으로 추가 작업이 필요하다는 의미(클라이언트를 새로운 URL로 이동) 87 | * 301(Moved Permanently): 요청한 자원의 URL이 변경됨, 새로운 URL이 응답에 있을 수도 있음 88 | * 302(Found): 요청한 자원의 URL이 일시적으로 변경됨, 새롭게 변경된 URL이 나중에 만들어질 수도 있어 클라이언트는 동일한 URI로 요청해야 함 89 | * 4xx: 클라이언트 에러 응답 90 | * 401(Unauthorized): 클라이언트는 요청에 대한 응답을 받기위해 인증이 필요 91 | * 403(Forbidden): 클라이언트는 자원에 접근할 권리가 없음, 401과 다르게 서버가 클라이언트가 누구인지 알 고 있음 92 | * 5xx: 서버 에러 응답 93 | 94 |
95 |
96 | 97 | 98 |
99 | HTTP와 HTTPS의 차이 100 |
101 | 102 | #### HTTP 103 | * 웹 브라우저와 웹 서버가 통신하기 위한 프로토콜 104 | * 평문 통신으로 `도청` 가능 105 | * 암호화하지 않음 106 | * 통신 상대를 확인하지 않아 `위장` 가능 107 | * 송신자를 확인할 수 없음 108 | * 완전성을 증명하지 않아 `변조` 가능 109 | * 완전성: 송신 내용과 수신 내용이 같은 것 110 | 111 | #### HTTPS (HTTP Secure) 112 | * HTTP에 SSL/TLS 기반의 Secure Socket을 활용한 프로토콜 113 | * 웹 브라우저와 웹 서버가 각각 키를 가지며 `그 키를 통해 암호화/복호화하여 HTTP통신`을 하기 때문에 클라이언트와 서버만이 데이터를 열람 가능 114 | 115 |
116 |
117 | 118 | 119 |
120 | 대칭키 암호화 121 |
122 | 123 | #### 정의 124 | * 하나의 키로 암/복호화를 모두 하는 방식 125 | 126 | #### 장단점 127 | * 암호화 연산 속도가 빠르기 때문에 효율적인 암호 시스템을 구축할 수 있음 128 | * 키 전달 및 관리에 어려움: 데이터를 보낼 때, 암호키도 함께 전송하는데 암호키 자체는 암호화가 되지 않은 평문으로 분실하거나 타인에게 노출되면 보안에 매우 취약 129 | 130 |
131 |
132 | 133 | 134 |
135 | 비대칭키(공개키) 암호화 136 |
137 | 138 | #### 정의 139 | * 암/복호화를 하는 키를 분리한 방식 140 | * 대칭키 암호화 방식의 키 전달의 취약점을 해결하기 위해 나온 방법 141 | * 비공개키(개인키)는 자신만이 소유하여 사용, 공개키는 타인에게 공개 142 | 143 | #### 장단점 144 | * 대칭키 암호화 방식의 키 전달 문제를 해결 145 | * 암/복호화를 위해 복잡한 연산을 수행해 속도가 느림 146 | 147 |
148 |
149 | 150 | 151 |
152 | HTTPS 통신 과정 (SSL/TLS Handshaking) 153 |
154 | 155 | * 대칭키와 비대칭키를 조합해서 사용 156 | 157 | #### 과정 158 | * Client Hello: 웹 브라우저가 웹 서버에 접속, 사용 가능한 암호화 알고리즘(`Ciper Suite`) 목록 전달 159 | * Server Hello: 사용할 암호화 알고리즘(`Ciper Suite`) 선택 및 전달 160 | * Certificate: 웹 서버는 `인증서`를 웹 브라우저에게 전송 161 | * 인증서: 인증기관의 `개인키`로 암호화된 `사이트의 정보`와 웹 서버의 `공개키`가 있음 162 | * Server Key Exchange: 파라미터를 서버의 개인키로 암호화해서 전송, Ciper Suite의 알고리즘이 DH인 경우에만 수행 163 | * Server Hello Done: 웹 서버가 전송 164 | * Client Key Exchange 165 | * 웹 브라우저는 이미 가지고 있는 인증기관의 `공개키`로 웹 서버에서 받은 인증서를 `복호화` 해서 확인 166 | * 웹 브라우저는 실제 데이터의 암호화에 사용될 `대칭키`를 생성, 인증서에서 꺼낸 웹 서버의 `공개키`로 `암호화` 해서 웹 서버로 전송 167 | * 웹 서버는 자신의 `개인키`로 웹 브라우저가 보내온 `대칭키`를 `복호화` 해서 얻음 (비대칭키 암호화) 168 | * DH) 파라미터를 공개키로 암호화해서 전송 169 | * ChangeCipherSpec + Finish: 통신 준비 완료, 클라이언트가 전송 170 | * ChangeCipherSpec + Finish: 통신 준비 완료, 서버가 전송 171 | * 웹 브라우저가 전송했던 `대칭키`로 데이터를 암호화해서 주고 받음 172 | * 서버와 클라이언트는 일련의 과정을 거쳐 대칭키로 `Session Key`를 만들어 사용 173 | * `Pre Master Secret`(대칭키) -> `Master Secret` -> `Session Key` (클라이언트와 서버 각자가 진행) 174 | 175 | #### 참고 1 176 | ##### 인증기관 (Certification Authority, CA) 177 | * 인증기관으로부터 공인인증서를 발급받아 서버에 설치해야 HTTPS 통신 가능 178 | * 웹 서비스 제공자는 자신의 공개키와 개인키를 생성, `공개키를 인증기관에 보냄` 179 | * 인증기관은 공개키, 유효기간 등 정보를 포함하여 `인증기관의 개인키로 전자서명한 인증서를 발급` 180 | * 웹 서버는 인증서와 개인키를 가지게 되어 HTTPS 통신을 할 수 있게 됨 181 | * 클라이언트에는 여러 인증기관의 공개키와 인증서가 이미 설치되어 있음 182 | * 웹 서버와 통신 시, 인증기관의 `개인키`로 서명된 인증서를 클라이언트가 받으면 인증기관의 `공개키`로 복호화 가능 183 | 184 | #### 참고 2 185 | * SSL을 사용하면 `https://` 를 사용하여 웹서버에 접근 가능 186 | * 대칭키: 실제 데이터 암호화 방식 187 | * 공개키: 대칭키를 공유하기 위해 사용 188 | 189 |
190 |
191 | 192 | 193 |
194 | HSTS (HTTP Strict Transport Security) 195 |
196 | 197 | #### 정의 198 | * 강제적으로 `HTTPS Protocol`로만 접속하게 하는 기능 199 | * 브라우저는 HTTPS를 사용해야 하는 웹 사이트의 목록(`HSTS List`)을 만들고 이것을 사용 200 | * 일정시간 (max-age, HSTS 리스트에 존속하는 시간) 동안 HSTS 응답을 한 웹사이트에 대해서 https 접속을 강제화 201 | 202 | #### 사용 목적 203 | * SSL Stripping 공격(중간자 공격)을 방지하기 위해 사용 204 | * 사용자가 HTTPS를 지원하는 사이트에 HTTP로 접속 했을 때, 중간자 공격에 의해 HTTP 통신을 하게 되어 공격자에게 정보가 노출되는 것을 방지 205 | * HSTS를 사용하면 HTTP 요청에 HSTS 헤더가 발견될 경우, 즉시 중단 206 | 207 |
208 |
209 | 210 | 211 |
212 | 쿠키와 세션 213 |
214 | 215 | * HTTP 통신에서 Connectionless, Stateless 보완 216 | 217 | #### 쿠키 218 | * `클라이언트의 로컬(브라우저)`에 저장되는 `키와 값`이 들어있는 `작은` 텍스트 파일 219 | * 보안에 나쁨: 파일로 저장해 탈취와 변조 가능, 응답/요청 시에 스니핑 위험이 있음 220 | * 브라우저를 종료해도 파일로 남음 221 | * 파일에서 읽어 속도 빠름 222 | 223 | #### 세션 224 | * 일정 시간동안 `같은 브라우저`에서 들어오는 요구를 하나의 상태로 보고 그 상태를 객체로 `서버`에 `제한 없는` 파일로 저장하는 기술 225 | * 보안에 좋음: `sessionid`를 통해 데이터를 구분하여 처리하여 보안이 좋음 226 | * 브라우저 종료 시, 세션 삭제 227 | * 요청마다 서버에서 처리해 느림 228 | 229 | #### 쿠키의 동작 과정 230 | * 클라이언트가 서버에 요청 231 | * 서버는 `HTTP 응답 헤더`에 `set-cookie` 헤더를 추가하여 응답 -> 클라이언트는 쿠키 저장 232 | * 이후, 클라이언트는 전달받은 `쿠키`를 자동으로 요청헤더에 추가하여 요청(브라우저가 자동으로 추가) 233 | * 서버에서 쿠키를 참고하여 로직 수행 234 | 235 | #### 세션의 동작 과정 236 | * 클라이언트가 서버에 요청 237 | * 서버는 `세션`에 클라이언트에 대한 데이터를 저장하고 `HTTP 응답 헤더`에 `sessionid`를 추가하여 응답 238 | * 클라이언트는 이후 서버에 요청할 때 전달받은 `세션 쿠키`를 자동으로 요청헤더에 추가하여 요청 239 | * 서버에서 `sessionid`를 참고하여 로직 수행 240 | 241 |
242 |
243 | 244 | 245 |
246 | 캐시 247 |
248 | 249 | * 리소스들의 임시 저장소 250 | * 이미지나 css, js파일 등을` 브라우저나 서버 앞 단에 저장`해놓고 사용하는 것 251 | * 같은 자원을 로드(load)해야할 때, 해당 자원을 다시 불러오지 않고 캐시되어 있는 자원을 사용 252 | * `서버를 거치지 않아 속도 향상` 253 | * 캐시에 있는 것을 재사용하기 때문에 경우에 따라 변경된 자원을 참조할 수 없는 경우가 생김 254 | 255 |
256 |
257 | 258 | 259 |
260 | 웹 캐시 261 |
262 | 263 | #### 웹 캐시 264 | 265 | * 대부분의 브라우저에서는 `HTTP 헤더`에 캐시 구현이 포함되어 있어서 웹 캐시를 구현 266 | * 응답 헤더의 Last-Modified, Etag, Expires, Cache-Control 항목 등과 같은 여러 부분의 여러 개의 태그를 통해서 캐싱 267 | 268 | #### Cache-Control: HTTP 헤더를 통해 캐싱 정책을 정의 269 | * `no-cache`: 캐시가 유효한지 매번 서버에 재검증 요청 270 | * `no-store`: 캐싱하지 않음 271 | 272 | #### Last-Modified, If-Modified-Since 273 | * 브라우저는 최초 응답 시 받은 `Last-Modified` 값을 `If-Modified-Since` 헤더에 포함 시켜 페이지를 요청 274 | * 서버는 요청 파일의 수정 시간을 `If-Modified-Since`값과 비교하여 동일하다면 `304 Not Modified`로 응답하고 다르다면` 200 OK` 275 | * 브라우저는 응답 코드가 304인 경우 `캐시`에서 페이지를 로드하고 200이라면 새로 다운받은 후, `Last-Modified` 값을 갱신 276 | 277 | #### Etag, If-None-Match 278 | * 브라우저는 최초 응답 시 받은 `Etag` 값을 `If-None-Match` 헤더에 포함 시켜 페이지를 요청 279 | * 서버는 요청 파일의 `Etag` 값을 `If-None-Match` 값과 비교하여 동일하다면 `304 Not Modified`로 응답하고 다르다면 `200 OK`와 함께 새로운 `Etag` 값을 응답 헤더에 전송 280 | * 브라우저는 응답 코드가 304인 경우 `캐시`에서 페이지를 로드하고 200이라면 새로 다운받은 후, `Etag` 값을 갱신 281 | 282 | #### Expires 283 | * 브라우저는 최초 응답 시 받은 `Expires` 시간을 비교하여 기간 내라면 서버를 거치지 않고 바로 캐시에서 페이지를 로드 284 | 285 |
286 |
287 | 288 | 289 |
290 | 웹 서버와 웹 애플리케이션 서버의 차이점 291 |
292 | 293 | #### 웹 서버 294 | * Http 프로토콜을 기반으로, 클라이언트의 요청을 처리하는 서버 295 | * html이나 css 같은` 정적 컨텐츠`를 내려주거나 부하분산을 위한 프록시 역할을 주로 함 296 | * `정적 컨텐츠`만 처리하는 고성능 서버 297 | 298 | #### 웹 애플리케이션 서버 299 | * 보통 웹서버 뒤에서 DB 조회 및 다양한 로직 처리 요구 시, `동적 컨텐츠`를 처리하는 서버 300 | * tomcat, netty 301 | 302 |
303 |
304 | 305 | 306 |
307 | URI, URL, URN 308 |
309 | 310 | #### URI(Uniform Resource Identifier) 311 | * 자원을 고유하게 `식별`하고 `위치`를 지정하는 통합 자원 식별자 312 | * URL, URN 두 가지 형태 존재 313 | * 인터넷 프로토콜을 명시함 314 | * 예시: http://www.naver.com 315 | 316 | #### URL(Uniform Resource Location) 317 | * 특정 서버의 한 리소스에 대한 구체적인 `위치` 318 | * 자원의 위치와 접근 방법을 분명히 알려줌 319 | * 예시: http://test.com/test/test.pdf 는 test.com서버에서 test폴더안의 test.pdf 파일을 요청 320 | 321 | #### URN(Uniform Resource Name) 322 | * 자원의 위치와 독립적인 `이름` 323 | * URL이 변경되면 기존의 객체를 찾을 수 없다는 URL의 한계를 극복하기 위해 사용 324 | * 예시: urn:2.19.222 325 | 326 |
327 |
328 | 329 | 330 |
331 | REST (Representational State Transfer) 332 |
333 | 334 | #### REST 335 | 336 | * 자원을 `이름(표현)`으로 구분하여 자원의 `상태(정보)`를 주고 받는 것 337 | * `HTTP URI`를 통해 자원을 구분하고 `HTTP Method(POST, GET, PUT, DELETE)`를 통해 해당 자원에 대한 `CRUD` 연산을 적용 338 | 339 | #### REST가 필요한 이유 340 | * 다양한 클라이언트(다양한 브라우저, AOS, IOS)의 등장으로 멀티 플랫폼에 대한 지원 341 | * 클라이언트와 서버 간의 역할 분리, 분산 애플리케이션 구현에 적합 342 | 343 | #### REST 구성 요소 344 | * 자원(Resource): URI 345 | * 행위(Verb): HTTP Method 346 | * 표현(Representation): JSON, XML 347 | 348 |
349 |
350 | 351 | 352 |
353 | REST API 설계원칙 및 특징 354 |
355 | 356 | * `REST API`는 `REST 기반의 규칙들을 지켜서 설계된 API` 357 | 358 | #### 설계 원칙 359 | * 자원에 대한 정보는 `명사`로 표현하고 자원에 대한 행위는 `HTTP 메소드`로 표현 360 | * URI에 `HTTP 메소드`, `동사`를 포함하지 않음 361 | * `/(슬래시)`를 `계층`관계를 나타내는데 사용하되 마지막 문자에 `/`를 포함하지 않음 362 | * `소문자`와 `-(하이픈)`를 사용 363 | * 대소문자에 따라 다른 자원으로 인식될 수 있음 364 | * 밑줄(_)은 사용하지 않음 365 | * 브라우저는 form-data 형식의 submit 으로 보내고 서버에서는 json 형태로 보내는 식의 분리보다는 둘 다 form-data 형식으로 보내든 하나로 통일 366 | 367 | #### REST 특징 368 | * 일관성 369 | * 동일 API로 일관된 처리 370 | * 서버-클라이언트 구조 371 | * 클라이언트는 서버 내부 작업을 몰라도 됨 372 | * 각각 독립적으로 개발 가능 373 | * Stateless (무상태) 374 | * HTTP는 Stateless해 서버가 클라이언트의 상태를 저장하지 않음 375 | * 요청에는 필요한 모든 정보가 포함되어야 함 376 | * Cacheable (캐시 처리 가능) 377 | * HTTP 프로토콜의 기존 인프라를 활용해 캐싱 가능 378 | * 응답에 캐시 가능한지 불가능한지 명시 필요 379 | * Self-Descriptive Message 380 | * API의 메시지만 보고도 이해 가능하도록 설계 381 | * HATEOAS 382 |
383 |
384 | 385 |
386 | REST (API) 장단점 387 |
388 | 389 | #### 장점 390 | * HTTP를 사용하므로 웹 인프라를 그대로 이용 가능 (별도의 인프라 필요 없음) 391 | * HTTP 표준 프로토콜을 따르는 모든 플랫폼에서 사용 가능 392 | * MSA에 적합하여 재사용에서 이점이 존재 393 | 394 | #### 단점 395 | * 명확한 표준이 존재하지 않아 사람마다 다르게 해석하고 사용할 수 있음 396 | * HTTP를 사용하므로 HTTP 통신 모델에 제약적 397 | * 사용 가능한 메소드가 제한적 398 | 399 |
400 |
401 | 402 | 403 |
404 | RESTful 405 |
406 | 407 | * `REST 원리를 따르는 시스템`을 나타내기 위해 사용하는 용어 408 | * RESTful한 API를 구현하는 목적은 성능 향상이 아니라 `일관적인 컨벤션`을 통한 API의 이해도 및 호환성을 높이는 것 409 | 410 | #### RESTful 하지 못한 경우 411 | * 모든 CRUD 연산을 POST로 처리하는 API 412 | * URI에 Resource, Id 외의 정보가 들어가는 경우 413 | 414 |
415 |
416 | 417 | 418 |
419 | HTTP GET과 POST 420 |
421 | 422 | #### GET 423 | * 자원을 `조회`하는 메소드 424 | * `URL의 파라미터`로 전달되어 `길이 제한`이 있어 많은 데이터 전송 불가 425 | 426 | #### POST 427 | * 자원을 `생성`하는 메소드 428 | * `HTTP Request Message의 Body`에 담겨 전달되어 길이 제한 없음 429 | 430 | #### 공통점 431 | * 서버로 데이터를 전송할 수 있음 432 | 433 |
434 |
435 | 436 | 437 |
438 | HTTP POST와 PUT 439 |
440 | 441 | #### POST 442 | * 자원을 `생성`하는 메소드 443 | * 같은 요청을 반복할 경우, 새로운 자원을 계속 생성 444 | * 멱등X 445 | 446 | #### PUT 447 | * 자원을 `생성 및 수정`하는 메소드 448 | * 자원의 `식별자`를 이미 알고있는 상태 -> request message와 함께 넘어온 식별자의 자원을 만드는 것 449 | * 같은 요청을 반복할 경우, 처음에는 자원이 없기 때문에 생성되고 그 이후는 생성되지 않음 450 | * 멱등 451 | 452 | #### POST 요청 예시 453 | 454 | * 아래 요청을 2번 반복할 경우 455 | ``` 456 | POST /new 457 | { 458 | "name": "고양이", 459 | "grade": 1 460 | } 461 | ``` 462 | 463 | * 식별자가 다른 2개의 자원 생성 464 | ``` 465 | { "id": 1, "name": "고양이", "grade": 1 } 466 | { "id": 2, "name": "고양이", "grade": 1 } 467 | ``` 468 | 469 | #### PUT 요청 예시 470 | 471 | * 아래 요청을 2번 이상 반복할 경우 472 | * POST와 다르게 요청에 식별자 포함 473 | ``` 474 | PUT /new/3 475 | { 476 | "name": "강아지", 477 | "grade": 2 478 | } 479 | ``` 480 | * 처음에는 자원이 없기 때문에 생성되고, 그 이후는 생성되지 않음 481 | ``` 482 | { "id": 3, "name": "강아지", "grade": 2 } 483 | ``` 484 | 485 |
486 |
487 | 488 | 489 |
490 | HTTP PATCH와 PUT 491 |
492 | 493 | #### PATCH 494 | * 자원의 `일부분을 수정`할 경우 495 | 496 | #### PUT 497 | * 자원 `전체를 수정/생성`할 경우 498 | * 요청을 보내지 않은 필드는 `DEFAULT` 값으로 변경되므로 요청 시에 모든 필드를 전송해야 됨 499 | 500 |
501 |
502 | 503 | 504 |
505 | HTTP 멱등성 506 |
507 | 508 | * 같은 요청을 반복하는 경우, 모든 요청에 따른 `서버의 상태가 같아야` 함 509 | * 안전한 메소드(GET, 서버의 상태 변경X)는 서버의 상태를 변경시키지 않음 510 | * 멱등한 메소드(PUT, DELETE, GET)는 서버의 상태를 변경시킬 수도 있고 아닐 수도 있음 511 | * POST는 멱등이 아니면서 안전하지도 않음 512 | 513 |
514 |
515 | 516 | 517 |
518 | JWT (JSON Web Token) 519 |
520 | 521 | * `Json` 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token 522 | * Header, Payload, Signature로 구성 523 | * 세션은 사용자의 수 만큼 서버 메모리를 차지하기 때문에, 최근에는 세션의 문제를 보완한 토큰 기반의 인증방식을 사용하는 추세 524 | 525 |
526 |
527 | --------------------------------------------------------------------------------