├── 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 | 
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 | 
342 | * 이진 트리를 확장해서, 더 많은 수의 자식을 가질 수 있게 일반화 시킨 자료구조
343 | * 균형 트리: 루트 ~ 리프의 거리가 일정한 트리
344 | * Branch 노드: Key와 Data 저장
345 |
346 | #### B+ 트리
347 |
348 | 
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 | 
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 | 
65 | * 네트워크 어떠한 계층에서 다른 계층으로 데이터가 전달될 때 한 덩이리의 단위를 PDU(Protocal Data Unit)이라고 함
66 | * PDU는 메타 정보를 갖고 있는 `헤더`와 데이터를 의미하는 `페이로드`로 구성되며 계층마다 부르는 명칭이 다름
67 |
68 | #### 캡슐화와 비캡슐화
69 | 
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 | 
106 | * 전송한 패킷의 ACK을 수신하면 다음 패킷 전송
107 |
108 | ##### Sliding Window - Go Back N
109 | 
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 | 
131 | * 송신 측에서 1개의 프레임을 송신하고, 수신측에서 수신된 프레임의 에러 유무에 따라 ACK 혹은 NAK를 보내는 방식
132 |
133 | ##### Go Back N ARQ과 SR(Selective-Reject) ARQ
134 | 
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 | 
155 | * CWND를 기본 값에서 시작하여 1씩 증가시키는 방법
156 |
157 | ##### Slow Start
158 | 
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 | 
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 | 
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 | 
248 |
249 | #### IPv4 IPv6 패킷
250 | 
251 | 
252 |
253 |
254 |
255 |
256 |
257 | 클래스 기반 할당 방식
258 |
259 |
260 | #### 클래스 기반 할당 방식
261 | 
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 | 
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 | 
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 | 
354 |
355 | #### 도메인
356 | * 네트워크 상에서 컴퓨터를 식별하는 호스트명
357 |
358 | #### DNS
359 | * 컴퓨터를 식별하는 호스트명인 도메인을 실제 서버와 연결 시켜주는 시스템
360 |
361 |
362 |
363 |
364 |
365 | GSLB (Global Server Load Balancing)
366 |
367 |
368 | 
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 | 
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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------