├── .DS_Store ├── Algorithm ├── README.md └── img │ ├── BST.png │ ├── BST_delete1.png │ ├── BST_delete2.png │ ├── BST_delete3-2.png │ ├── BST_delete3.png │ ├── BST_insert.png │ ├── BST_search.png │ ├── BST_time_complexity.png │ ├── Dijkstra_0.png │ ├── Dijkstra_1.png │ ├── Dijkstra_2.png │ ├── Dijkstra_3.png │ ├── Dijkstra_4.png │ ├── Sieve_of_Eratosthenes.gif │ ├── binary-tree.png │ ├── disjoint_set_path_compression.PNG │ ├── disjoint_set_union_by_rank.PNG │ ├── dual-pivot-quicksort.png │ ├── graph_BFS.png │ ├── graph_DFS.png │ ├── graph_chart.png │ ├── heap.png │ ├── heap_delete.png │ ├── heap_insert.png │ ├── heap_sort1.PNG │ ├── heap_sort2.PNG │ ├── heap_sort3.PNG │ ├── heap_sort4.PNG │ ├── max_heap.png │ ├── min_heap.png │ ├── quicksort-partition.png │ ├── segment-tree-range.png │ ├── segment-tree.png │ ├── tree-degree-level.png │ ├── trie-principle.png │ ├── trie-search.png │ ├── 그래프_DFS.png │ ├── 그래프_경로.png │ ├── 그래프_종류.png │ └── 그래프_표.png ├── CommonSense ├── README.md └── img │ ├── MSA_Monolithic_Microservices.png │ ├── MSA_msa.png │ ├── MSA_team1.png │ ├── MSA_team2.png │ ├── call-by-value1.png │ └── call-by-value2.png ├── Database ├── README.md └── img │ ├── cartesian-join-row.png │ ├── cartesian-join-where.png │ ├── cartesian-join.png │ ├── cartesian-right-join-row.png │ ├── cartesian-right-join.png │ ├── cartesian-where-row.png │ ├── clustering_active_active.PNG │ ├── clustering_active_standby.PNG │ ├── clustering_load_balance.PNG │ ├── clustering_primay_secondary.PNG │ ├── db-sql-joins.jpg │ ├── outer-join.png │ ├── outer-on-and.png │ ├── outer-on-where.png │ ├── replication_master_slave.PNG │ ├── replication_master_slave2.PNG │ ├── replication_master_slave3.PNG │ └── self-join.png ├── DesignPattern ├── README.md └── img │ ├── AbFactory1.png │ ├── AbFactory2.png │ ├── AbFactory3.png │ ├── Deco1.png │ ├── Deco2.png │ ├── Deco3.png │ ├── Deco4.png │ ├── Deco5.png │ ├── Strategy_class.PNG │ ├── Strategy_robot.PNG │ ├── Strategy_strategy.PNG │ ├── adapter.jpg │ ├── adapter.png │ ├── command_class_diagram.PNG │ ├── command_example1.png │ ├── command_example2.PNG │ ├── factory1.gif │ ├── factory2.png │ ├── factory3.png │ ├── factory4.png │ └── state_class_diagram.PNG ├── LICENSE ├── Network ├── README.md └── img │ ├── Asyn-block.gif │ ├── Asyn-nonblock.gif │ ├── IPv4_Datagram.png │ ├── IPv6_Datagram.png │ ├── IPv6_Datagram_Payload.png │ ├── Syn-block.gif │ └── Syn-nonblock.gif ├── OS ├── .DS_Store ├── README.md └── img │ ├── .DS_Store │ ├── IPC_Message_passing_shared_memory.png │ ├── IPC_message_queue.png │ ├── IPC_pipe.png │ ├── IPC_socket.png │ ├── Thread-share.png │ ├── banker's-algorithm.png │ ├── context-switching.jpg │ ├── fcfs_gantt.png │ ├── fcfs_process.png │ ├── fifo-page-replace.png │ ├── hierarchical paging.png │ ├── interrupt_process.PNG │ ├── lru-page-replace.png │ ├── opt-page-replace.png │ ├── os-booting.png │ ├── os-shell-kernel.png │ ├── os.png │ ├── paging.png │ ├── pcb.jpg │ ├── pcb_create.png │ ├── preem_sjf_gantt.png │ ├── preem_sjf_process.png │ ├── priori_gantt.png │ ├── priority_process.png │ ├── process.png │ ├── resource-allocation-graph-algorithm.png │ ├── resource-allocation-graph1.png │ ├── resource-allocation-graph2.png │ ├── role-of-os.png │ ├── rr_gantt.png │ ├── sjf_gantt.png │ ├── sjf_process.png │ ├── stsructure-of-os.png │ ├── thread.png │ ├── virtual-memory.png │ └── wait-for-graph.png ├── README.md └── _Interview └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/.DS_Store -------------------------------------------------------------------------------- /Algorithm/img/BST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST.png -------------------------------------------------------------------------------- /Algorithm/img/BST_delete1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_delete1.png -------------------------------------------------------------------------------- /Algorithm/img/BST_delete2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_delete2.png -------------------------------------------------------------------------------- /Algorithm/img/BST_delete3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_delete3-2.png -------------------------------------------------------------------------------- /Algorithm/img/BST_delete3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_delete3.png -------------------------------------------------------------------------------- /Algorithm/img/BST_insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_insert.png -------------------------------------------------------------------------------- /Algorithm/img/BST_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_search.png -------------------------------------------------------------------------------- /Algorithm/img/BST_time_complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/BST_time_complexity.png -------------------------------------------------------------------------------- /Algorithm/img/Dijkstra_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/Dijkstra_0.png -------------------------------------------------------------------------------- /Algorithm/img/Dijkstra_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/Dijkstra_1.png -------------------------------------------------------------------------------- /Algorithm/img/Dijkstra_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/Dijkstra_2.png -------------------------------------------------------------------------------- /Algorithm/img/Dijkstra_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/Dijkstra_3.png -------------------------------------------------------------------------------- /Algorithm/img/Dijkstra_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/Dijkstra_4.png -------------------------------------------------------------------------------- /Algorithm/img/Sieve_of_Eratosthenes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/Sieve_of_Eratosthenes.gif -------------------------------------------------------------------------------- /Algorithm/img/binary-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/binary-tree.png -------------------------------------------------------------------------------- /Algorithm/img/disjoint_set_path_compression.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/disjoint_set_path_compression.PNG -------------------------------------------------------------------------------- /Algorithm/img/disjoint_set_union_by_rank.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/disjoint_set_union_by_rank.PNG -------------------------------------------------------------------------------- /Algorithm/img/dual-pivot-quicksort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/dual-pivot-quicksort.png -------------------------------------------------------------------------------- /Algorithm/img/graph_BFS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/graph_BFS.png -------------------------------------------------------------------------------- /Algorithm/img/graph_DFS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/graph_DFS.png -------------------------------------------------------------------------------- /Algorithm/img/graph_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/graph_chart.png -------------------------------------------------------------------------------- /Algorithm/img/heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap.png -------------------------------------------------------------------------------- /Algorithm/img/heap_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap_delete.png -------------------------------------------------------------------------------- /Algorithm/img/heap_insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap_insert.png -------------------------------------------------------------------------------- /Algorithm/img/heap_sort1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap_sort1.PNG -------------------------------------------------------------------------------- /Algorithm/img/heap_sort2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap_sort2.PNG -------------------------------------------------------------------------------- /Algorithm/img/heap_sort3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap_sort3.PNG -------------------------------------------------------------------------------- /Algorithm/img/heap_sort4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/heap_sort4.PNG -------------------------------------------------------------------------------- /Algorithm/img/max_heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/max_heap.png -------------------------------------------------------------------------------- /Algorithm/img/min_heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/min_heap.png -------------------------------------------------------------------------------- /Algorithm/img/quicksort-partition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/quicksort-partition.png -------------------------------------------------------------------------------- /Algorithm/img/segment-tree-range.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/segment-tree-range.png -------------------------------------------------------------------------------- /Algorithm/img/segment-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/segment-tree.png -------------------------------------------------------------------------------- /Algorithm/img/tree-degree-level.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/tree-degree-level.png -------------------------------------------------------------------------------- /Algorithm/img/trie-principle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/trie-principle.png -------------------------------------------------------------------------------- /Algorithm/img/trie-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/trie-search.png -------------------------------------------------------------------------------- /Algorithm/img/그래프_DFS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/그래프_DFS.png -------------------------------------------------------------------------------- /Algorithm/img/그래프_경로.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/그래프_경로.png -------------------------------------------------------------------------------- /Algorithm/img/그래프_종류.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/그래프_종류.png -------------------------------------------------------------------------------- /Algorithm/img/그래프_표.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Algorithm/img/그래프_표.png -------------------------------------------------------------------------------- /CommonSense/img/MSA_Monolithic_Microservices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/CommonSense/img/MSA_Monolithic_Microservices.png -------------------------------------------------------------------------------- /CommonSense/img/MSA_msa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/CommonSense/img/MSA_msa.png -------------------------------------------------------------------------------- /CommonSense/img/MSA_team1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/CommonSense/img/MSA_team1.png -------------------------------------------------------------------------------- /CommonSense/img/MSA_team2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/CommonSense/img/MSA_team2.png -------------------------------------------------------------------------------- /CommonSense/img/call-by-value1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/CommonSense/img/call-by-value1.png -------------------------------------------------------------------------------- /CommonSense/img/call-by-value2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/CommonSense/img/call-by-value2.png -------------------------------------------------------------------------------- /Database/README.md: -------------------------------------------------------------------------------- 1 | # Database 2 | 3 | - [키](#키) 4 | 5 | - [SQL - 기초 Query](#sql---기초-query) 6 | 7 | - [SQL - JOIN](#JOIN) 8 | 9 | - [SQL Injection](#sql-injection) 10 | 11 | - [SQL vs NoSQL](#SQLvsNoSQL) 12 | 13 | - [Anomaly와 정규화](#anomaly와-정규화) 14 | 15 | - [인덱스](#인덱스) 16 | 17 | - [트랜잭션](#트랜잭션) 18 | 19 | - [트랜잭션 격리 수준](#트랜잭션-격리수준) 20 | 21 | - [레디스](#레디스) 22 | 23 | - [Hint](#hint) 24 | 25 | - [클러스터링](#클러스터링(Clustering)) 26 | 27 | - [리플리케이션](#리플리케이션(Replication)) 28 | 29 | - [데이터베이스 튜닝](#데이터베이스-튜닝) 30 | 31 | 32 | 33 | 34 | # 키 35 | ## 정의 36 | 37 | 테이블에서 튜플을 구별하는 역할을 하는 속성 38 | 39 | ## 특성 40 | 41 | - 유일성 42 | 43 | 한 릴레이션에서 모든 튜플은 서로 다른 키 값을 가져야 한다. 44 | 45 | - 최소성 46 | 47 | 꼭 필요한 최소한의 속성들로만 키를 구성한다. 48 | 49 | 50 | ## 종류 51 | 52 | 1. 후보키 53 | 54 | 유일성과 최소성을 만족하는 키 55 | 56 | 2. 슈퍼키 57 | 58 | 유일성을 만족하지만 최소성을 만족하지 못하는 속성 59 | 60 | 4. 기본키 61 | 62 | 후보키 중에서 기본적으로 사용하기 위해 선택한 키 63 | 64 | 개체 무결성 제약조건: 기본키를 구성하는 모든 속성은 널 값을 가질 수 없다. 65 | 66 | 5. 대체키 67 | 68 | 기본키로 선택되지 못한 후보키 69 | 70 | 7. 외래키 71 | 72 | 다른 릴레이션의 기본키를 참조하는 속성 73 | 74 | 참조 무결성 제약조건: 외래키는 참조할 수 없는 값을 가질 수 없다. 75 | 76 | 77 |
78 | 79 | ---- 80 | 81 | # SQL - 기초 Query 82 | 83 | ## SQL이란? 84 | SQL이란 Structed Query Language(구조적 질의 언어)의 줄임말로, **관계형 데이터베이스 관리 시스템(RDBMS)** 의 데이터를 관리하기 위해 설계된 특수 목적의 프로그래밍 언어이다. 85 | 86 | 관계형 데이터베이스 관리 시스템에서 자료의 검색과 관리, 데이터베이스 스키마 생성과 수정, 데이터베이스 객체 접근 조정 관리를 위해 고안되었다. 87 | 88 | 많은 데이터베이스 관련 프로그램들이 SQL을 표준으로 채택하고 있다. 89 | 90 | SQL의 구성요소로는 크게 3가지 **데이터 정의어(DDL)**, **데이터 조작어(DML)**, **데이터 제어어(DCL)** 으로 구성된다. 91 | 92 |
93 | 94 | **+) 테이블이란?** 95 | 96 | 테이블이란 항상 이름을 가지고 있는 리스트로, 데이터가 저장되어있는 공간을 의미한다. 97 | 98 | 테이블은 **행(ROW)** 과 **열(COLUMN)** 그리고 거기에 대응하는 **값(FIELD)** 으로 구성되어 있다. 99 | 100 |

101 | 102 |

103 | 104 |
105 | 106 | ## SQL의 언어적 특성 107 | 1. SQL은 대소문자를 가리지 않는다. (단, 서버 환경이나 DBMS 종류에 따라 데이터베이스 또는 필드명에 대해 대소문자를 구분하기도 한다) 108 | 2. SQL 명령은 반드시 `세미콜론(;)`으로 끝나야 한다. 109 | 3. 고유의 값은 `따옴표(")`로 감싸준다. 110 | ```sql 111 | SELETE * FROM EMP WHERE NAME = 'James'; 112 | ``` 113 | 114 | 4. SQL에서 객체를 나타낼 때는 백틱(\`\`)으로 감싸준다. 115 | ```sql 116 | SELETE \`COST\`, \`TYPE\` FROM \`INVOIVE\`; 117 | ``` 118 | 119 | 5. 주석은 일종의 도움말로, 주석 처리된 문장은 프로그램에서 동작하지 않는다. 한 줄 주석은 문장 앞에 `--`를 붙여서 사용한다. 120 | ```sql 121 | -- SELETE * FROM EMP; 122 | ``` 123 | 124 | 6. 여러 줄 주석은 `/* */`으로 감싸준다. 125 | 126 |
127 | 128 | ## SQL과 일반 프로그래밍 언어의 차이점 129 |

130 | 131 |

132 |
133 | 134 | ## SQL 데이터 종류 135 | 1. **int** 136 | 137 | 정수 자료형으로, 예를 들어 물건의 가격, 수량 등을 저장하는 데 사용된다. 138 | 139 | 해당 자료형을 통해 -2147483648 ~ 2144483647의 값을 저장할 수 있다. 140 | 141 | 2. **float** 142 | 143 | 실수 자료형으로, int는 소수점 이하의 부분이 없지만 float는 3.14와 같이 소숫점 이하의 부분까지 저장한다. 144 | 145 | 따라서 사람들의 키나 몸무게 등처럼 소숫점 아래까지 저장해야 하는 경우에 사용한다. 146 | 147 | 3. **char** 148 | 149 | 문자열 자료형으로, char(nn)과 같은 방식으로 사용한다. 이 경우 nn글자를 저장하게 된다. 150 | 151 | 예를 들어 char(5) 일 경우, 5글자를 저장하며 5글자가 되지 않을 경우 공백을 추가하여 5글자를 맞춘다. 152 | 153 | 'elice'와 같이 작은따옴표를 이용해 문자열인 것을 표시한다. 154 | 155 | 4. **varchar** 156 | 157 | 문자열 자료형으로, char과 다른 점은 char의 경우 정해진 글자보다 짧으면 공백을 추가하지만 varchar은 공백을 추가하지 않고 그대로 저장한다. 158 | 159 | varchar2와 동의어이다. 160 | 161 | 5. **date** 162 | 163 | 년, 월, 일을 저장하는 날짜 자료형으로, 예를 들어 1945년 8월 15일을 나타내기 위해서는 '1945-08-15'라고 작성한다. 164 | 165 | 해당 자료형을 통해 '1001-01-01'~ '9999-12-31'까지 저장할 수 있다. 166 | 167 | 6. **datetime** 168 | 169 | 년, 월, 일, 시, 분, 초까지 저장하는 날짜와 시각 자료형이다. 170 | 171 | 예를 들어 1945년 8월 15일 12시 0분 0초를 나타내기 위해서는 '1945-08-15 12:00:00'라고 작성한다. 172 | 173 | 해당 자료형을 통해 '1001-01-01 00:00:00'~ '9999-12-31 23:59:59'까지 저장할 수 있다. 174 | 175 | 7. **time** 176 | 177 | 시간, 분, 초를 저장하는 시간 자료형이다. 178 | 179 | 예를 들어 10시간 13분 35초를 나타내기 위해서는 '10:13:35'라고 작성한다. 180 | 181 | 해당 자료형을 통해 '-838:59:59' ~ '838:59:59'까지 저장할 수 있다. 182 | 183 |
184 | 185 | ## 데이터 정의어(DDL) - CREATE, ALTER, DROP, TRUNCATE문 186 | 187 | 테이블이나 관계의 구조를 생성하는데 사용하며 CREATE, ALTER, DROP, TRUNCATE문 등이 있다. 188 | 189 | ### CREATE 문 190 | 191 | * 테이블을 구성하고, 속성과 속성에 관한 제약을 정의하며, 기본키 및 외래키를 정의하는 명령이다. 192 | 193 | * **PRIMARY KEY** 는 기본키를 정할 때 사용하고, **FOREIGN KEY** 는 외래키를 지정할 때 사용하며, **ON UPDATE** 와 **ON DELETE** 는 외래키 속성의 수정과 튜플 삭제 시 동작을 나타낸다. 194 | 195 | * **NOT NULL** (NULL 값을 가질 수 없음), **UNIQUE** (같은 값이 있으면 안됨), **DEFAULT** num(값이 입력되지 않은 경우 기본값 num을 저장) 등 속성에 제약사항을 추가할 수 있다. 196 | 197 | ``` sql 198 | CREATE TABLE NewBook ( 199 | bookname VARCHAR2(20) NOT NULL, 200 | publisher VARCHAR2(20) UNIQUE, 201 | price NUMBER DEFAULT 10000, 202 | PRIMARY KEY (bookname, publisher)); 203 | ``` 204 | 205 |
206 | 207 | ### ALTER 문 208 | 209 | * ALTER문은 생성된 테이블의 속성과 속성에 관한 제약을 변경하며, 기본키 및 외래키를 변경한다. 210 | 211 | * **ADD, DROP** 은 속성을 추가하거나 제거할 때 사용한다. 212 | 213 | * **MODIFY** 는 속성의 기본값을 설정하거나 삭제할 때 이용한다. 214 | 215 | ``` sql 216 | -- NewBook 테이블에 VARCHAR2(13)의 자료형을 가진 isbn 속성 추가 217 | ALTER TABLE NewBook ADD isbn VARCHAR2(13); 218 | 219 | -- NewBook 테이블의 isbn 속성의 데이터 타입을 NUMBER형으로 변경 220 | ALTER TABLE NewBook MODIFY isbn NUMBER; 221 | 222 | -- NewBook 테이블의 isbn 속성을 삭제 223 | ALTER TABLE NewBook DROP COLUMN isbn; 224 | ``` 225 | 226 |
227 | 228 | ### DROP 문 229 | 230 | * DROP문은 테이블 자체를 삭제하는 명령이다. 231 | 232 | * 테이블의 구조와 데이터를 모두 삭제하므로 사용에 주의해야 함(데이터만 삭제하려면 DELETE) 233 | 234 | ``` sql 235 | DROP TABLE NewBook; 236 | ``` 237 | 238 |
239 | 240 | ### TRUNCATE 문 241 | 242 | * 테이블에 있는 데이터를 모두 제거하는 명령이다. (한번 삭제시 돌이킬 수 없음.) 243 | 244 | ``` sql 245 | TRUNCATE TABLE NewBook; 246 | ``` 247 | 248 |
249 | 250 | ## 데이터 조작어(DML) - SELECT, INSERT, DELETE, UPDATE문 251 | 252 | 테이블에 데이터를 검색, 삽입, 수정, 삭제하는데 사용하며 SELECT, INSERT, DELETE, UPDATE문 등이 있다. 253 | 254 | 여기서 SELECT 문은 특별히 Query문(질의어)라고도 한다. 255 | 256 | ### CRUD란? 257 | 258 | Create(생성), Retrieve(검색), Update(수정), Delete(삭제)의 첫 자를 따서 만든 단어이다. 259 | 260 | * Create : 데이터베이스 객체 생성 261 | 262 | : INSERT INTO (새로운 레코드 추가) 263 | 264 | * Update : 데이터베이스 객체 안의 데이터 수정 265 | 266 | : UPDATE (특정 조건의 레코드의 컬럼 값 수정) 267 | 268 | * Delete : 데이터베이스 객체의 데이터 삭제 269 | 270 | : DELETE (특정 조건의 레코드 삭제) 271 | 272 | * Retrieve : 데이터베이스 객체 안의 데이터 검색 273 | 274 | : SELETE (조건을 만족하는 레코드를 찾아 특정 컬럼 값(모두 표시하려면 * )을 표시) 275 | 276 |
277 | 278 | ### INSERT 문 279 | 280 | * 테이블에 새로운 튜플을 삽입하는 명령으로, 대량삽입(Bulk Insert)란 한번에 여러 개의 튜플을 삽입하는 방법이다. 281 | 282 | * **INSERT INTO** 테이블(필드이름1, 필드이름2) **VALUES** (값1, 값2); 283 | 284 | ``` sql 285 | -- Book 테이블에 새로운 도서 '스포츠 의학' 삽입 286 | INSERT INTO Book(bookid, bookname, publisher) 287 | VALUES (14, '스포츠 의학', '한솔의학서적'); 288 | ``` 289 | 290 |
291 | 292 | ### UPDATE 문 293 | 294 | * UPDATE문은 특정 속성 값을 수정하는 명령이다. 295 | 296 | * **UPDATE** 테이블 **SET** 필드이름1=값1, 필드이름2=값2 **WHERE** 조건문; 297 | 298 | ``` sql 299 | -- Customer 테이블에서 고객번호가 5인 고객의 주소를 '대한민국 부산'으로 변경 300 | UPDATE Customer 301 | SET address='대한민국 부산' 302 | WHERE custid = 5; 303 | ``` 304 | 305 |
306 | 307 | ### DELETE 문 308 | 309 | * DELETE문은 테이블에 있는 기존 튜플을 삭제하는 명령이다. 310 | 311 | * **DELETE FROM** 테이블 **WHERE** 조건문; 312 | 313 | ``` sql 314 | -- Customer 테이블에서 고객번호가 5인 고객 삭제 315 | DELETE FROM Customer 316 | WHERE custid=5; 317 | 318 | -- 모든 고객 삭제 319 | DELETE FROM Customer; 320 | ``` 321 | 322 |
323 | 324 | ### SELETE 문 325 | 326 | * 테이블에 저장된 데이터를 검색하는 명령어이다. 327 | 328 | * **SELETE** 컬럼명 **FROM** 테이블명 **WHERE** 조건문; 329 | 330 | * WHERE절에 조건으로 사용할 수 있는 술어 331 | 332 |

333 | 334 |

335 | 336 | * 집계 함수의 종류 337 | 338 |

339 | 340 |

341 | 342 |
343 | 344 | ``` sql 345 | -- 가격이 10,000원 이상 20,000원 이하인 도서 검색 346 | SELETE * 347 | FROM Book 348 | WHERE price BETWEEN 10000 AND 20000; 349 | 350 | -- 도서 이름에 '축구가 포함된 출판사 검색 351 | SELETE bookname, publisher 352 | FROM Book 353 | WHERE bookname LIKE '%축구%'; 354 | 355 | -- 도서를 가격의 내림차순으로 검색, 만약 가격이 같다면 출판사의 오름차순으로 검색 356 | SELETE * 357 | FROM Book 358 | ORDER BY price DESC, publisher ASC; 359 | 360 | -- 2번 김연아 고객이 주문한 도서의 총 판매액 구하기 361 | SELETE SUM(saleprice) AS 총매출 362 | FROM Orders 363 | WHERE custid=2; 364 | 365 | -- 서점의 도서 판매 건수 구하기 366 | SELECT COUNT(*) 367 | FROM Orders; 368 | ``` 369 | 370 |
371 | 372 | ## 데이터 제어어(DCL) - GRANT, REVOKE문 373 | 374 | 데이터 접근을 통제하기 위해 데이터의 사용 권한을 관리하는데 사용하며, GRANT, REVOKE문 등이 있다. 375 | 376 | * 권한의 유형과 종류 377 | 378 | 1. 시스템 권한 379 | 380 | * CREATE USER : 계정 생성 권한 381 | 382 | * DROP USER : 계정 삭제 권한 383 | 384 | * DROP ANY TABLE : 테이블 삭제 권한 385 | 386 | * CREATE SESSION : 데이터베이스 접속 권한 387 | 388 | * CREATE TABLE : 테이블 생성 권한 389 | 390 | * CREATE VIEW : 뷰 생성 권한 391 | 392 | * CREATE SEQUENCE : 시퀀스 생성 권한 393 | 394 | * CREATE PROCEDURE : 함수 생성 권한 395 | 396 | 2. 객체 권한 397 | 398 | * ALTER : 테이블 변경 권한 399 | 400 | * INSERT : 데이터 조작 권한 401 | 402 | * DELETE : 데이터 조작 권한 403 | 404 | * SELECT : 데이터 조작 권한 405 | 406 | * UPDATE : 데이터 조작 권한 407 | 408 | * EXECUTE : PROCEDURE 실행 권한 409 | 410 |
411 | 412 | ### GRANT 문 413 | 414 | * 특정 데이터베이스 사용자에게 특정 작업에 대한 수행 권한을 부여한다. 415 | 416 | ```sql 417 | GRANT 권한1, 권한2 TO 사용자계정; 418 | 419 | GRANT 권한1, 권한2 ON 객체명 TO 사용자계정; 420 | ``` 421 | 422 |
423 | 424 | ### REVOKE 문 425 | 426 | * 특정 데이터베이스 사용자에게 특정 작업에 대한 수행 권한을 박탈하거나 회수 한다. 427 | 428 | ```sql 429 | REVOKE 권한1, 권한2 FROM 사용자계정; 430 | 431 | REVOKE 권한1, 권한2 ON 객체명 FROM 사용자계정; 432 | ``` 433 | 434 |
435 | 436 | ### 트랜잭션 제어 (COMMIT, ROLLBACK, CHECKPOINT문) 437 | 438 | 안전한 거래를 보장하기 위해, 즉 동시에 다수의 작업을 안전하게 처리하기 위해 사용한다. 439 | 440 | * COMMIT : 트랜잭션 확정 441 | * ROLLBACK : 트랜잭션 취소 442 | * CHECKPOINT : 복귀지점 설정 443 | 444 |
445 | 446 | --- 447 | 448 |
449 | 450 | # JOIN 451 | 452 | 여러 테이블을 하나의 테이블처럼 논리적으로 연결하여 사용하는 방법 453 | 454 | 일반적으로, 둘 이상 테이블에서 데이터가 필요한 경우 JOIN을 시도한다. 455 | 456 | ![DataBase SQL JOINS](https://github.com/hongcheol/CS-study/blob/main/Database/img/db-sql-joins.jpg?raw=true) 457 | 458 | ## JOIN과 집합 연산자의 차이 459 | 460 | - 집합 연산자 : 두 개 이상의 SELECT문의 결과 값을 세로로 연결한 것 461 | - JOIN : 두 개 이상의 테이블 데이터를 가로로 연결한 것 462 | 463 |
464 | 465 | ## EQUI JOIN 466 | 467 | 두 테이블의 특정 열의 값들이 정확하게 일치할 때 이를 기준으로 데이터를 연결하는 방법 468 | 469 | - Default Join 방법 470 | - 일반적으로 PK, FK 관계에 의해 JOIN을 시도하지만 일반 컬럼을 기준으로 JOIN을 시도하는 것도 가능 471 | - JOIN하려는 두개 이상 테이블이 동일한 이름의 컬럼을 사용한다면 SELECT 시 반드시 테이블 명을 밝혀야함 472 | - N개의 테이블을 JOIN할 경우 최소 N-1개의 JOIN 조건이 필요함 473 | 474 | ### SQL 형태 475 | 476 | > Q. 회사 직원들의 사번, 이름과 함께 해당 직원들이 속한 부서번호와 부서명을 조회한다. 477 | > 478 | > - 직원 테이블의 직원이 속한 부서번호 정보가 담긴 열과 부서 테이블의 부서번호 열을 기준으로 JOIN하면 두 테이블의 부서번호가 동일할 때 직원 정보와 각 부서명을 바로 연결할 수 있다. 479 | 480 | ```sql 481 | SELECT e.empno, e.ename, e.deptno, d.dname 482 | FROM emp e, dept d 483 | WHERE e.deptno = d.deptno; 484 | ``` 485 | 486 | - 위의 쿼리문과 같이 `=` 연산자를 이용하여 완전히 일치하는 특정 열을 기준으로 조인 487 | - JOIN 조건을 `ON` 절이나 `WHERE` 절에 부여할 수 있음 488 | - 단, OUTER JOIN을 시도할 경우 여러 조건과 함께 JOIN 조건을 `ON` 절로 부여하는 것과 `WHERE` 절로 부여할 때 결과가 달라지므로 주의 489 | 490 | ## INNER JOIN 491 | 492 | - EQUI JOIN과 함께 Default Join 방법으로 사용됨 493 | - SQL 형태는 EQUI JOIN과 같음 494 | 495 | ### INNER JOIN과 EQUI JOIN 496 | 497 | - EQUI JOIN : `=` 연산자를 이용하여 `ON` 절이나 `WHERE` 절에 조건을 부여하여 JOIN하는 방법 498 | - INNER JOIN : JOIN 조건을 만족하는 행에 대해서만 결과 값이 나오는 JOIN 499 | 500 | ### INNER JOIN과 OUTER JOIN 501 | - INNER JOIN : 두 테이블의 **교집합**으로 JOIN하는 개념 502 | - OUTER JOIN : 두 테이블의 **합집합**으로 JOIN하는 개념 503 | 504 | ```python 505 | for x in A : 506 | for x in B : 507 | if (A.x = B.x) JOIN 508 | ``` 509 | 510 | 위와 같이 A 테이블과 B 테이블의 x 열을 기준으로 JOIN을 시도하는 경우 511 | 512 | INNER JOIN은 아무리 A 테이블에 x 열이 존재한다고 하더라도 **B 테이블의 x열의 값과 같지 않다면 그 값은 결과에 포함되지 않는다**. 따라서 내부 for문에 해당하는 B 테이블 조건이 결과의 핵심이다. 513 | 514 | 반면 OUTER JOIN은 A 테이블과 B 테이블의 각각의 **x 열의 값이 같지 않다고 할지라도 외부 for문에 해당하는 A 테이블에 값이 존재한다면 결과에 포함시킨다**. 따라서 외부 for문에 해당하는 A 테이블 조건이 결과의 핵심이다. 만약 외부 for문에 B 테이블을, 내부 for문에 A 테이블을 조건으로 둔다면 결과는 위 경우와 반대로 **외부 for문에 해당하는 B 테이블에 존재하는 값을 기준으로 결과에 포함시킨다**. 515 | 516 |
517 | 518 | ## NON-EQUI JOIN 519 | 520 | 한 테이블의 열의 값이 다른 테이블 열의 값과 정확히 일치하지 않지만 JOIN을 시도해야하는 경우 사용하는 방법 521 | 522 | - EQUI JOIN과 달리 `=` 연산자는 사용할 수 없고(값이 정확히 일치하지 않음), `Between`, `>`, `>=`, `<`, `<=` 등 다른 연산자를 이용해 JOIN 조건을 부여해야 함. 523 | 524 | ### SQL 형태 525 | 526 | > Q. 회사 직원들의 사번, 이름과 함께 해당 직원들의 급여 등급을 조회한다. 527 | > 528 | > - 직원 테이블의 직원 급여 열과 급여등급 테이블의 급여 하한선과 상한선 열들을 **비교하여** JOIN하면 직원의 급여와 급여가 **속하는 범위**의 등급을 연결할 수 있다. 529 | 530 | ```sql 531 | SELECT e.empno, e.ename, e.salary, s.grade 532 | FROM emp e, salgrade s 533 | WHERE e.salary BETWEEN s.losal AND s.hisal; 534 | ``` 535 | 536 | - 위의 쿼리문과 같이 `=`가 아닌 다른 연산자를 이용하여 연산자 결과 범위에 포함되는 값을 결과로 도출 537 | 538 |
539 | 540 | ## OUTER JOIN 541 | 542 | JOIN 조건에 만족하지 않는 레코드를 결과에 포함하고자 할 때 사용하는 JOIN 방법 543 | 544 | 어느 한쪽 테이블에는 데이터가 존재하는데 다른쪽 테이블에는 해당 데이터가 존재하지 않는 경우 INNER JOIN을 한다면 검색 결과에 누락이 발생할 수 있음 545 | 546 | 따라서 **합집합**을 구하고자 할 때 사용할 수 있음 547 | 548 | ### OUTER JOIN 방법 549 | 550 | - LEFT [OUTER] JOIN : JOIN 키워드의 왼쪽 테이블을 기준으로 해당 테이블에 속한 데이터는 모두 포함 551 | - RIGHT [OUTER] JOIN : JOIN 키워드의 오른쪽 테이블을 기준으로 해당 테이블에 속한 데이터는 모두 포함 552 | - FULL [OUTER] JOIN : JOIN 키워드의 양쪽 테이블을 기준으로 모든 테이블에 속한 데이터를 포함 553 | 554 | ### SQL 형태 555 | 556 | > Q. 회사 모든 직원들의 사번, 이름과 함께 해당 직원들의 부서명을 조회한다. 단, 아직 부서를 배치받지 못한 직원까지 포함하여 회사의 모든 직원들이 조회되어야 한다. 557 | > 558 | > - 직원 테이블의 부서 번호 열과 부서 테이블의 부서 번호 열의 값이 일치하는 경우를 JOIN한다. 단, 직원 누락이 발생하면 안되므로 **직원 테이블의 모든 데이터가 포함되는 OUTER JOIN**을 한다. 559 | 560 | ```sql 561 | SELECT e.employee_id, e.last_name, d.department_name 562 | FROM employees e LEFT JOIN departments d 563 | ON e.department_id = d.department_id; 564 | ``` 565 | 566 | ![outer join](https://github.com/hongcheol/CS-study/blob/main/Database/img/outer-join.png?raw=true) 567 | 568 | - 모든 데이터가 포함되어야하는 테이블의 위치에 따라 LEFT와 RIGHT 조건을 부여하여 사용한다. 569 | 570 |
571 | 572 | ## SELF JOIN 573 | 574 | 한 테이블의 열을 같은 테이블 내 다른 열과 연결하는 방법으로, 같은 테이블을 2개 이상의 테이블인 것처럼 사용할 수 있음 575 | 576 | - 주로 데이터 간 **계층형 관계**를 표현할 수 있을 때 사용 577 | - ex) 선후배 관계, 상사와 부하 직원 관계, 게시글과 답글 관계 등 578 | - FROM 절 뒤에 동일한 테이블 명을 2번 표현하되, 둘을 구분하기 위해 반드시 **별칭**을 기재해야 함 579 | - 컬럼 역시 어떤 기준 테이블인지 테이블 별칭에 연결하여 표현해야 함 580 | 581 | ### SQL 형태 582 | 583 | > Q. 회사 직원들의 이름과 함께 자신의 상사 번호, 상사 이름, 상사의 직원 번호를 조회한다. 584 | > 585 | > - 직원 테이블의 상사 번호 열과 직원 테이블의 직원 번호 열의 값이 동일한 경우를 JOIN한다. 586 | 587 | ```sql 588 | SELECT e1.last_name, e1.manager_id, e2.last_name, e2.employee_id 589 | FROM employees e1, employees e2 590 | WHERE e1.manager_id = e2.employee_id; 591 | ``` 592 | 593 | ![self join](https://github.com/hongcheol/CS-study/blob/main/Database/img/self-join.png?raw=true) 594 | 595 | - 동일하지만 서로 다른 목적을 위해 중복된 두 테이블을 구분해야 함. 따라서 별칭을 꼭 지어줘야 함. 596 | 597 |
598 | 599 | ## Cartesian JOIN(Cross JOIN) 600 | 601 | - JOIN 조건의 오류로 인해 한 테이블에 있는 모든 레코드가 다른 테이블의 레코드와 JOIN이 되는 경우 602 | - A 테이블 레코드 수가 `a`개, A 테이블 레코드 수가 `b`개라면 카티시안 조인 결과 `a*b`개의 결과가 도출됨. 603 | - 서로 관계가 없는 레코드도 함께 묶여 결과로 출력되므로 필요없는 결과가 중복되거나 지나치게 많은 결과가 출력될 수 있음 604 | 605 | ### SQL 예제 606 | 607 | > Q. 도시명과 나라명을 조회한다. 608 | > 609 | > - 두 테이블의 JOIN 기준 없이 JOIN하므로 레코드의 컬럼 간 의미가 없는 레코드가 저장됨. 610 | 611 | ```sql 612 | SELECT country_name, city 613 | FROM countries, locations; 614 | ``` 615 | 616 | ![cartesian join](https://github.com/hongcheol/CS-study/blob/main/Database/img/cartesian-join.png?raw=true) 617 | 618 | ![cartesian join rows](https://github.com/hongcheol/CS-study/blob/main/Database/img/cartesian-join-row.png?raw=true) 619 | 620 | - 위의 결과 23개의 city 레코드 수와 25개의 country_name 레코드 수가 곱해져 총 575개의 결과가 도출됨. 621 | - 의도적으로 위와 같은 결과를 도출하려는 것이 아니라면, `WHERE`절 혹은 `ON` 절에 JOIN 조건을 명시해야함. 622 | 623 | > Q. 각 나라 별 도시를 조회한다. 624 | 625 | ```sql 626 | SELECT c.country_name, l.city 627 | FROM countries c, locations l 628 | WHERE c.country_id = l.country_id; 629 | ``` 630 | 631 | ![cartesian join sol1](https://github.com/hongcheol/CS-study/blob/main/Database/img/cartesian-join-where.png?raw=true) 632 | 633 | ![cartesian join sol1](https://github.com/hongcheol/CS-study/blob/main/Database/img/cartesian-where-row.png?raw=true) 634 | 635 | > Q. 모든 나라의 도시를 조회한다. 636 | 637 | ```sql 638 | SELECT c.country_name, l.city 639 | FROM locations l RIGHT JOIN countries c 640 | ON c.country_id = l.country_id; 641 | ``` 642 | 643 | ![cartesian join sol2](https://github.com/hongcheol/CS-study/blob/main/Database/img/cartesian-right-join.png?raw=true) 644 | 645 | ![cartesian join sol2](https://github.com/hongcheol/CS-study/blob/main/Database/img/cartesian-right-join-row.png?raw=true) 646 | 647 |
648 | 649 | ## ANSI JOIN 650 | 651 | 미국 국립 표준 협회(American National Standards Institute,ANSI)에서 지정한 SQL 문법 652 | 653 | ### NATURAL JOIN 654 | 655 | 두 테이블의 JOIN할 열들이 완전히 동일한 필드명(컬럼명)을 가질 경우 해당 열들을 JOIN 656 | 657 | - 단, 두 테이블의 열이 같은 필드명을 가지고 있다고 할지라도, **서로 다른 데이터를 포함한 채로 필드명만 동일**할 수도 있으므로 주의하여 사용해야 한다. 658 | 659 | #### SQL 형태 660 | 661 | > Q. 회사 직원 별 직무를 조회한다. 662 | > 663 | > - 직원 테이블의 직무 번호와 직무 테이블의 직무 번호가 일치하는 경우 JOIN 664 | 665 | ```sql 666 | SELECT last_name, job_title 667 | FROM employees NATURAL JOIN jobs; 668 | ``` 669 | 670 |
671 | 672 | ### JOIN ~ USING 673 | 674 | 두 테이블의 JOIN 기준 열을 USING에 명시하여 JOIN하는 방법 675 | 676 | #### SQL 형태 677 | 678 | > Q. 회사 직원 별 직무를 조회한다. 679 | > 680 | > - 직원 테이블의 직무 번호와 직무 테이블의 직무 번호가 일치하는 경우 JOIN 681 | 682 | ```sql 683 | SELECT last_name, job_title 684 | FROM employees JOIN jobs 685 | USING(job_id); 686 | ``` 687 | 688 |
689 | 690 | ### JOIN ~ ON 691 | 692 | 두 테이블 간 공통된 이름의 열이 존재하지 않거나, 일반 쿼리 조건인 `WHERE` 절과 구분하기 위해 `ON`절에 기준을 명시하여 JOIN하는 방법 693 | 694 | #### OUTER JOIN에서의 WHERE과 ON 695 | 696 | > Q. IT 부서에서 일하는 회사 직원들의 이름을 조회한다. 697 | > 698 | > - 직원 테이블의 부서 번호 열과 부서 테이블의 부서 번호 열의 값이 일치하는 경우를 JOIN한다. 단, 직원 누락이 발생하면 안되므로 **직원 테이블의 모든 데이터가 포함되는 OUTER JOIN**을 한다. 699 | 700 | ```sql 701 | SELECT e.last_name, d.department_name 702 | FROM employees e LEFT JOIN departments d 703 | ON e.department_id = d.department_id 704 | WHERE d.department_name = 'IT'; 705 | ``` 706 | 707 | ![outer join on where](https://github.com/hongcheol/CS-study/blob/main/Database/img/outer-on-where.png?raw=true) 708 | 709 | - 위의 쿼리 결과 `WHERE`절로 IT부서 직원들을 필터링 한 뒤, JOIN을 한다. 710 | - 따라서 IT부서 직원들이 아니라면 결과에 포함되지 않는다. 711 | 712 | ```sql 713 | SELECT e.last_name, d.department_name 714 | FROM employees e LEFT JOIN departments d 715 | ON e.department_id = d.department_id 716 | AND d.department_name = 'IT'; 717 | ``` 718 | 719 | ![outer join on and](https://github.com/hongcheol/CS-study/blob/main/Database/img/outer-on-and.png?raw=true) 720 | 721 | - 위의 쿼리 결과 `ON`절을 통째로 기준으로 삼아 JOIN을 한다. 722 | - 따라서 바깥 for문에 해당하는 employees 테이블의 데이터가 안쪽 for문에 해당하는 departments 테이블의 데이터를 하나씩 확인하며 부서 번호가 동일하고 IT부서라면 JOIN으로 관계를 표현하지만, 그렇지 않을 경우에도 **employees 테이블에 속한 데이터면 결과에 포함**한다. 723 | 724 | OUTER JOIN 시 `ON`과 `WHERE` 사용에 따라 다른 결과가 나올 수 있으므로 주의해야 한다. 만약 필터링으로 결과 데이터를 축소해야 한다면, 1번 예시처럼 **JOIN 조건은 `ON`에, 필터링 조건은 `WHERE`에 표현**하는 것이 좋다. 725 | 726 |
727 | 728 | --- 729 | 730 |
731 | 732 | 733 | # SQL Injection 734 | 735 | ## SQL 인젝션이란? 736 | 737 | SQL 인젝션은 웹 사이트의 보안상 허점을 이용해 특정 SQL 쿼리문을 전송해 공격자가 원하는 데이터베이스의 중요한 정보를 가져오는 해킹 기법이다. 738 | 739 | 대부분 클라이언트가 입력한 데이터를 제대로 필터링하지 못하는 경우에 발생한다. 740 | 741 | 공격의 쉬운 난이도에 비해 피해가 상당하기 때문에 보안 위협 1순위로 불릴만큼 중요한 기법이다. 742 | 743 | ## SQL 인젝션의 종류와 공격 방법 744 | 745 | ### Error based SQL Injection 746 | 747 | > 논리적 에러를 이용한 SQL 인젝션 748 | 749 | 가장 많이 쓰이고, 대중적인 공격 기법이다. 750 | 751 | ```sql 752 | SELECT * FROM Users WHERE id = 'INPUT1' AND password = 'INPUT2' 753 | ``` 754 | 755 | ```sql 756 | SELECT * FROM Users WHERE id = ' ' OR 1=1 -- 'AND password = 'INPUT2' 757 | --> SELECT * FROM Users 758 | ``` 759 | 760 | 첫번째 쿼리문은 일반적으로 로그인 시 많이 사용되는 SQL 구문이다. 761 | 762 | 해당 구문에서 입력값에 대한 검증이 없음을 확인하고, 악의적인 사용자가 임의의 SQL 구문을 주입했다. 763 | 764 | 주인된 내용은 **`' OR 1=1--`** 으로 WHERE 절에 있는 ' 를 닫아주기 위한 ' 와 OR 1=1 라는 구문을 이용해 WHERE절을 모두 참으로 만들고, —를 넣어주어서 뒤의 구문을 주석 처리를 해준 것이다. 765 | 766 | 매우 간단한 구문이지만 결론적으로 Users 테이블에 있는 모든 정보를 조회하게 됨으로써 가장 먼저 만들어진 계정으로 로그인에 성공하게 된다. 767 | 768 | 보통 관리자 계정을 맨 처음으로 만들기 때문에 관리자 계정으로 로그인할 수 있게 되며, 악의적인 사용자는 관리자의 권한을 이용해 또 다른 2차피해를 발생시킬 수 있게 된다. 769 | 770 | ### UNION based SQL Injection 771 | 772 | > UNION 명령어를 이용한 SQL 인젝션 773 | 774 | UNION은 여러개의 SQL문을 합쳐 하나의 SQL 문으로 만들어주는 방법이다. 775 | 776 | 정상적인 쿼리문에 Union 키워드를 사용해 인젝션에 성공하면, 원하는 쿼리문을 실행할 수 잇게 된다. 777 | 778 | Union Injection을 성공하기 위해서는 두 테이블의 컬럼 수가 같아야 하고, 데이터 형이 같아야 한다는 두 가지의 조건이 있다. 779 | 780 | ```sql 781 | SELECT * FROM Board WHERE title like '%INPUT%' OR contents like '%INPUT%' 782 | ``` 783 | 784 | ```sql 785 | SELECT * FROM Board WHERE title LIKE '% ' 786 | UNION SELECT null, id, password FROM Users 787 | -- %' AND contents '% UNION SELECT null, id, password FROM Users -- %' 788 | 789 | ``` 790 | 791 | 첫번째 쿼리문은 Board라는 테이블에서 게시글을 검색하는 쿼리문이다. 792 | 793 | 입력값을 title과 content 컬럼의 데이터랑 비교한 뒤 비슷한 글자가 있는 게시글을 출력한다. 794 | 795 | 여기서 입력값으로 Union 키워드와 함께 컬럼 수를 맞춰서 SELECT 구문을 넣어주게 되면 두 쿼리문이 합쳐져서 하나의 테이블로 보여지게 된다. 796 | 797 | 현재 인젝션한 구문은 사용자의 id와 password를 요청하는 쿼리문이다. 798 | 799 | 인젝션이 성공하게 되면, 사용자의 개인정보가 게시글과 함께 화면에 보여지게 된다. 800 | 801 | password를 그대로 DB에 저장하지는 않겠지만 인젝션이 가능하다는 점에서 이미 그 이상의 보안위험에 노출되어 있다. 802 | 803 | 이 공격도 역시 입력값에 대한 검증이 없기 때문에 발생한다. 804 | 805 | ### Blind SQL Injection 806 | 807 | > Boolean based Blind SQL 인젝션 808 | 809 | Blind SQL Injection은 데이터베이스로부터 특정한 값이나 데이터를 전달받지 않고 단순히 참과 거짓의 정보만 알 수 있을 때 사용한다. 810 | 811 | 로그인 폼에 SQL Injection이 가능하다고 가정했을 때, 서버가 응답하는 로그인 성공과 로그인 실패 메시지를 이용해 DB의 테이블 정보 등을 추출한다. 812 | 813 | 즉, 쿼리를 삽입하였을 때 쿼리의 참과 거짓에 대한 반응을 구분할 수 있을 때 사용되는 기술이다. 814 | 815 | ```sql 816 | SELECT * FROM Users WHERE id = 'INPUT1' ANS password = 'INPUT2' 817 | ``` 818 | 819 | ```sql 820 | SELECT * FROM Users WHERE id = ' abc123' and 821 | ASCII(SUBSTR((SELECT name FROM information_schema.tables 822 | WHERE table_type='base table' limit 0,1),1,1)) > 100 -- 823 | ``` 824 | 825 | 위 쿼리는 Blind Injection을 이용해 DB의 테이블명을 알아내는 방법이다. 826 | 827 | 인젝션이 가능한 로그인 폼을 통해 악의적인 사용자는 임의로 가입한 abc123이라는 아이디와 함께 뒤의 구문을 주입한다. 828 | 829 | 해당 구문은 MySQL에서 테이블 명을 조회하는 구문으로 limit 키워드를 통해 하나의 테이블만 조회하고, SUBSTR 함수로 첫 글자만, 그리고 마지막으로 ASCII를 통해 ascii 값으로 변환한다. 830 | 831 | 만약 조회되는 테이블 명이 Users 라면 'U' 가 조회될 것이고, 뒤의 100이라는 숫자와 값을 비교하게 된다. 832 | 833 | 거짓이면 로그인 실패, 참이 될 때까지 뒤의 100이라는 숫자를 변경해가면서 비교한다. 834 | 835 | 참이 나오는 것을 통해 단기간 내에 테이블 명을 알아낼 수 있다. 836 | 837 | > Time based SQL 838 | 839 | 어떤 경우에는 응답의 결과가 항상 동일해 해당 결과만으로 참과 거짓을 판별할 수 없는 경우가 있을 수 있다. 840 | 841 | 이런 경우 시간을 지연시키는 쿼리를 주입(Injection)하여 응답 시간의 차이로 참과 거짓 여부를 판별할 수 있다. 842 | 843 | 사용되는 함수는 MySQL 기준 SLEEP 과 BENCHMARK 이다. 844 | 845 | ```sql 846 | SELECT * FROM Users WHERE id = 'INPUT1' AND password = 'INPUT2' 847 | ``` 848 | 849 | ```sql 850 | SELECT * FROM Users WHERE id = ' abc123' OR 851 | (LENGTH(DATABASE())=1 AND SLEEP(2)) 852 | -- ' AND password = 'INPUT2' 853 | ``` 854 | 855 | 위 쿼리문은 Time based SQL Injection을 사용해 현재 사용하고 있는 데이터베이스의 길이를 알아내는 방법이다. 856 | 857 | 로그인 폼에 주입되었으며 임의로 abc123이라는 계정을 생성한다. 858 | 859 | 악의적인 사용자가 해당 구문을 주입하면, LENGH 함수는 문자열의 길이를 반환하고, DATABASE 함수는 데이터베이스의 이름을 반환한다. 860 | 861 | 주입된 구문에서, LENGTH(DATABASE()) = 1 가 참이면 SLEEP(2) 가 동작하고, 거짓이면 동작하지 않는다. 862 | 863 | 이를 통해 숫자 1 부분을 조작해 데이터베이스의 길이를 알 수 있다. 864 | 865 | 만약 SLEEP 이라는 단어가 치환 처리되었다면, 다른 방법으로 BENCHMARK 나 WAIT 함수를 사용할 수 있다. 866 | 867 | ### Stored Procedure SQL Injection 868 | 869 | > 저장된 프로시저에서의 SQL Injection 870 | 871 | 저장 프로시저(Stored Procedure)은 일련의 쿼리들을 모아 하나의 함수처럼 사용하기 위한 것이다. 872 | 873 | 공격에 사용되는 대표적인 저장 프로시저는 MS-SQL에 있는 xp_cmdshell로 윈도우 명령어를 사용할 수 있게 된다. 874 | 875 | 단, 공격자가 시스템 권한을 획득해야 하므로 공격난이도가 높으나 공격에 성공한다면 서버에 직접적인 피해를 입힐 수 있는 공격이다. 876 | 877 | ### Mass SQL Injection 878 | 879 | > 다량의 SQL Injection 공격 880 | 881 | 기존 SQL Injection과 달리 한번의 공격으로 다량의 데이터베이스가 조작되어 큰 피해를 입히는 것을 의미한다. 882 | 883 | 보통 MS-SQL을 사용하는 ASP 기반 웹 애플리케이션에서 많이 사용되며, 쿼리문은 HEX 인코딩 방식으로 인코딩해 공격한다. 884 | 885 | 보통 데이터베이스 값을 변조해 데이터베이스에 악성스크립트를 삽입하고, 사용자들이 변조된 사이트에 접속 시 좀비 PC로 감염되게 한다. 886 | 887 | 이렇게 감염된 좀비 PC들은 DDos 공격에 사용된다. 888 | 889 | ## SQL 인젝션 대응방안 890 | 891 | ### 입력 값에 대한 검증 892 | 893 | SQL Injection에 사용되는 기법과 키워드는 엄청 많다. 894 | 895 | 따라서 사용자의 입력 값에 대한 검증이 필요하다. 896 | 897 | 서버 단에서 화이트리스트를 기반으로 검증해야 하며, 블랙리스트를 기반으로 검증하게 되면 차단리스트를 많이 등록해야 하고, 하나라도 빠지면 공격에 성공하게 된다. 898 | 899 | 공백으로 치환하는 방법도 많이 쓰이는데, 이 방법도 취약한 방법이다. 900 | 901 | 예시로 SE**SELECT**LECT 라고 입력 시 중간의 SELECT가 공백으로 치환되면 SELECT 라는 키워드가 완성된다. 902 | 903 | 공백 대신 공격 키워드와를 의미 없는 단어로 치환되어야 한다. 904 | 905 | ### Prepared Statement 구문 사용 906 | 907 | Prepared Statement 구문을 사용하게 되면, 사용자의 입력 값이 데이터베이스의 파라미터로 들어가기 전 DBMS가 미리 컴파일하여 실행하지 않고 대기한다. 908 | 909 | 그 후 사용자의 입력 값을 문자열로 인식하여 공격쿼리가 들어간다고 해도, 사용자의 입력은 이미 의미 없는 단순 문자열이기 때문에 전체 쿼리문도 공격자의 의도대로 작동하지 않는다. 910 | 911 | ### Error Message 노출 금지 912 | 913 | 공격자가 SQL Injection을 수행하기 위해서는 데이터베이스의 정보(테이블, 컬럼 명)가 필요하다. 914 | 915 | 데이터베이스 에러 발생 시 따로 처리하지 않는다면, 에러가 발생한 쿼리문과 함께 에러에 관한 내용을 반환해주기 때문에 공격자에게는 힌트가 될 수 있다. 916 | 917 | 따라서 데이터베이스에 대한 오류가 발생할 때는 사용자에게 보여줄 수 있는 페이지를 제작하거나 메시지박스를 띄우도록 해야 한다. 918 | 919 | ### 웹 방화벽 사용 920 | 921 | 웹 공격 방어에 특화되어있는 웹 방화벽을 사용하는 것도 하나의 방법이다. 922 | 923 | 웹 방화벽은 소프트웨어형, 하드웨어형, 프록시형 세 가지 종류로 나눌 수 있다. 924 | 925 | 소프트웨어형은 서버 내에 직접 설치하는 방법이고, 하드웨어형은 네트워크 상에서 서버 앞 단에 직접 하드웨어 장비로 구성하는 것이며 마지막으로 프록시형은 DNS 서버 주소를 웹 방화벽으로 바꾸고 서버로 가는 트래픽이 웹 방화벽을 먼저 거치도록 하는 방법이다. 926 | 927 | ---- 928 | 929 |
930 | 931 | # SQLvsNoSQL 932 | 933 | ### [SQL (Structured Query Language) ] 934 | SQL은 RDBMS (관계형 데이터베이스 관리 시스템)의 데이터를 관리하기 위해 설계된 프로그래밍 언어입니다. SQL의 예시로는 *MySQL, PostgreSQL* 등이 있습니다. 935 | > 이 글에서는 SQL을 곧 RDBMS (관계형 데이터베이스) 로 사용함 936 | 937 | ### [NoSQL (Not Only Structured Query Language) ] 938 | NoSQL은 앞서 말한 SQL보다 덜 제한적인 모델을 이용해 데이터의 저장 및 검색 메커니즘을 제공합니다. NoSQL의 예시로는 *mongoDB, redis* 등이 있습니다. 939 | 940 | ## 데이터의 구조 (Structure) 941 | 942 | ### [SQL] 943 | ![image](https://user-images.githubusercontent.com/55073084/132952907-020564fe-37c9-4ebc-9540-a1b9a8f6e4f9.png) 944 | ###### 출처 : https://siyoon210.tistory.com/130 945 | 946 | SQL에서는 엄격한 스키마(데이터 저장 구조)를 원칙으로 하기 때문에 **스키마를 준수하지 않는 형식의 데이터는 저장할 수 없습니다.** 947 | 948 | ### [NoSQL] 949 | ![image](https://user-images.githubusercontent.com/55073084/132977185-4b854ca8-25cf-45b4-bdbd-bbaa8cbdf574.png) 950 | ###### 출처 : https://siyoon210.tistory.com/130 951 | NoSQL에서는 정해진 스키마가 없습니다. SQL에서는 정해진 스키마를 따르지 않는다면 데이터를 추가할 수 없었지만, **NoSQL에서는 다른 구조의 데이터를 같은 컬렉션에 추가할 수 있습니다.** 952 | 953 | > NoSQL에서는 레코드를 document, 테이블을 Collection이라고 부릅니다. 954 | 955 | 956 | ## 데이터의 관계 (Relationship) 957 | 958 | ### [ SQL ] 959 | ![image](https://user-images.githubusercontent.com/55073084/132953107-5e577ef2-cc60-4bda-9273-69ae87c3a99f.png) 960 | ###### 출처 : https://mjmjmj98.tistory.com/43 961 | 962 | 데이터들을 여러개의 테이블에 나누어서, 데이터들의 중복을 피할 수 있습니다. 963 | 964 | 만약 사용자가 구입한 상품들을 나타내기 위해서는, Customers(사용자), Products(상품), Orders(주문한 상품) 여러 테이블을 만들어야 하지만, 각각의 테이블들은 다른 테이블에 저장되지 않은 데이터를 가지고 있습니다. (중복된 데이터가 없습니다.) 965 | 966 | 이런 명확한 구조는 장점이 있습니다. **하나의 테이블에서 중복없이 하나의 데이터만을 관리하기 때문에, 다른 테이블에서 부정확한 데이터를 다룰 위험이 없습니다.** 967 | 968 | 969 | ### [ NoSQL ] 970 | ![image](https://user-images.githubusercontent.com/55073084/132977191-17ecfef9-0ac5-45fc-ae51-f83563e40162.png) 971 | ###### 출처 : https://mjmjmj98.tistory.com/43 972 | 반면 NoSQL에서는 보통 하나의 컬렉션(SQL에서의 테이블)에 관련 데이터를 모두 작성합니다. 973 | 974 | 일반적으로 관련 데이터를 동일한 컬렉션에 넣습니다. (RDBMS처럼 여러 테이블에 나누어 담지 않습니다.) 많은 Order(주문한 상품)이 있는 경우, 일반적인 정보를 모두 포함한 데이터를 Orders 컬렉션에 저장합니다. (즉, 관계형데이터 베이스에서 사용했던 Users나 Products 정보 또한 Orders에 포함해서 한꺼번에 저장됩니다.) 975 | 976 | 따라서 **여러 테이블 / 컬렉션에 조인할 필요없이 이미 필요한 모든 것을 갖춘 문서를 작성하게 됩니다.** (실제로 NoSQL DB에는 조인이라는 개념이 존재하지 않습니다.) 대신 컬렉션을 통해 데이터를 복제하여 각 컬렉션 일부분에 속하는 데이터를 정확하게 산출하도록 합니다. 977 | 978 | 이런 방식은 SQL과 다르게 중복된 데이터가 생기게 됩니다. 그래서 데이터를 업데이트 할 때마다 주의해야 합니다. (예를 들어 Customer에 John의 email을 추가했는데, Orders에는 이를 업데이트하지 않으면 문제가 발생합니다.) 979 | 980 | 981 | ## 데이터의 확장성 (Scalability) 982 | 두 종류의 데이터베이스를 비교할 때 살펴 봐야할 또 하나의 중요한 개념은 **확장(Scaling)** 입니다. (데이터베이스 서버의 확장성) 983 | 984 | 확장은 **수직적(vertical) 확장**과 **수평적(horizontal) 확장**으로 구별할 수 있습니다. 985 | - 수직적 확장이란 단순히 데이터베이스 서버의 성능을 향상시키는 것입니다. 986 | - 반면에 수평적 확장은 더 많은 서버가 추가되고 데이터베이스가 전체적으로 분산됨을 의미합니다. 987 | 988 | ### [ SQL(vertical scale)] 989 | 데이터가 저장되는 방식 때문에 SQL은 일반적으로 수직적 확장만을 지원합니다. 990 | 991 | ### [NoSQL(horizontal scale)] 992 | 반면에 NoSQL에서는 수평적 확장이 가능합니다. 993 | 994 | 995 | ## SQL vs NoSQL 장단점 996 | 997 | ### [SQL] 998 | #### 장점 999 | - 명확하게 정의된 스키마, **데이터의 무결성 보장** 1000 | - 데이터의 관계 덕분에 데이터는 중복없이 한 번만 저장됩니다. 1001 | 1002 | #### 단점 1003 | - 상대적으로 덜 유연합니다. **데이터 스키마는 사전에 계획**되어야 합니다. (나중에 수정하기가 번거롭거나 불가능 할 수도 있음) 1004 | - 관계를 맺고 있기 때문에 **JOIN문이 많은 매우 복잡한 쿼리**가 만들어 질 수 있습니다. 1005 | - 수평적 확장이 어렵고, 대체로 수직적 확장만 가능합니다. 즉 어떤 시점에서 (처리할 수 있는 처리량 관련하여) 성장 한계에 직면하게 됩니다. 1006 | 1007 | 1008 | ### [NoSQL] 1009 | #### 장점 1010 | - 스키마가 없기때문에, 훨씬 더 **유연합니다.** 즉, 언제든지 저장된 데이터를 조정하고 새로운 "필드"를 추가 할 수 있습니다. 1011 | - 데이터는 애플리케이션이 필요로 하는 형식으로 저장됩니다. 이렇게 하면 **데이터를 읽어오는 속도가 빨라집니다.** 1012 | - 수직 및 수평 확장이 가능하므로 데이터베이스가 애플리케이션에서 발생시키는 모든 읽기 / 쓰기 요청을 처리 할 수 있습니다. 1013 | 1014 | #### 단점 1015 | - 유연성 때문에, 데이터 구조 결정을 하지 못하고 미루게 될 수 있습니다. 1016 | - 일반적인 정보를 모두 포함한 데이터를 컬렉션에(SQL 처럼 하나의 테이블에 하나의 레코드가 아니라) 넣기 때문에 데이터 중복이 발생할 수 있습니다. 1017 | - 데이터가 여러 컬렉션에 중복되어 있기 때문에, **수정(update)를 해야 하는 경우 모든 컬렉션에서 수행**해야 합니다. (SQL에서는 중복된 데이터가 없기 때문에 한번만 수행하면 됩니다.) 1018 | 1019 | ## SQL vs NoSQL의 선택 1020 | SQL과 NoSQL을 적당하게 선택하기 위해서는 **어떤 데이터를 다루는지**, **어떤 어플리케이션에 사용되는지**를 고려해야 합니다. 1021 | 1022 | ### [SQL] 1023 | - 관계를 맺고 있는 **데이터가 자주 변경(수정)** 되는 애플리케이션일 경우 1024 | - **변경될 여지가 없고, 명확한 스키마**가 사용자와 데이터에게 중요한 경우 1025 | 1026 | ### [NoSQL] 1027 | - **정확한 데이터 구조를 알 수 없거나 변경 / 확장** 될 수 있는 경우 1028 | - **읽기(read)처리를 자주**하지만, 데이터를 자주 변경(update)하지 않는 경우 (즉, 한번의 변경으로 수십 개의 문서를 업데이트 할 필요가 없는 경우) 1029 | - 데이터베이스를 수평으로 확장해야 하는 경우 ( 즉, 막대한 양의 데이터를 다뤄야 하는 경우) 1030 | 1031 | 1032 | 1033 |
1034 |
1035 |
1036 | 1037 | 1038 | 1039 | # Anomaly와 정규화 1040 | 1041 |
1042 | 1043 | 1044 | ## 데이터 이상(Anomaly) 1045 | 1046 | 잘못된 데이터베이스 설계로 인해 데이터들의 불필요한 중복이 발생할 수 있다. 테이블에서 일부 속성들이 종속으로 인해 데이터의 중복이 발생하고, 테이블 조작 시 문제가 발생하는 현상을 **데이터 이상(Anomaly)** 이라고 한다. 이상의 종류에는 3가지가 있다. 1047 | 1048 | - 삽입 이상(Insertion Anomaly) 1049 | 1050 | - 삭제 이상(Deletion Anomaly) 1051 | 1052 | - 갱신 이상(Update Anomaly) 1053 | 1054 |
1055 |
1056 | 1057 |
1058 | 1059 | 1060 | ### 삽입 이상(Insertion Anomaly) 1061 | 1062 | 테이블에 새로운 데이터를 삽입할 때 불필요한 데이터도 함께 삽입해야 하는 이상. 즉, 일부 데이터만 삽입하고 싶어도 입력을 원치 않는 다른 데이터까지 함께 삽입해야 하는 현상을 뜻한다. 1063 |
1064 | 1065 |

1066 |

1067 | 1068 | 1069 |
1070 | 1071 |

1072 |

1073 | 1074 | 1075 | 1076 | 위와 같이 (학번, 수강과목)이 PK인 테이블을 가정해보자. 1077 | 1078 | 이때 수강과목은 정하지 않고 '엘싸'라는 학생 정보만 저장하고 싶어도 (학번, 수강과목)이 PK이기 때문에 수강과목 데이터를 비워둘 수 없다. 따라서 학생 정보만 삽입하기를 원해도 수강과목이라는 원치 않는 데이터까지 함께 삽입해야 한다. 1079 | 1080 |
1081 |
1082 | 1083 | ### 삭제 이상(Insertion Anomaly) 1084 | 1085 | 테이블에서 한 튜플을 삭제할 때 연쇄적으로 삭제가 발생하는 이상. 즉, 삭제를 원치 않는 데이터들까지 함께 삭제되는 현상을 뜻한다. 1086 | 1087 |
1088 | 1089 |

1090 |

1091 | 1092 | 1093 | 위 테이블에서 학번이 400, 수강과목 6번인 6행 데이터는 삭제하더라도 큰 문제가 없다. 하지만 학번이 200, 수강과목 2번인 2행 데이터를 삭제하게 되면 '다빈슨'이라는 학생의 정보까지 테이블 상에서 모두 사라지게 된다. 1094 | 1095 |
1096 |
1097 | 1098 | ### 갱신 이상(Insertion Anomaly) 1099 | 1100 | 튜플의 속성 값을 갱신할 때 일부 튜플들만 수정하여 데이터들 간에 불일치가 발생하는 이상. 1101 | 1102 |
1103 | 1104 |

1105 |

1106 | 1107 | 1108 | 1109 | 1110 | '하로롱'이라는 학생의 학부가 오락부로 바뀌었다고 가정해보자. 이때 미처 다른 튜플에 있는 정보를 수정하지 못한다면 '하로롱' 학생의 학부 정보 간의 불일치가 발생하게 된다. 1111 | 1112 | 1113 |
1114 |
1115 |
1116 | 1117 | --- 1118 | 1119 |
1120 | 1121 | ## 정규화(Normalization) 1122 | 1123 | 데이터 이상 방지를 위해 테이블 속성들 사이의 종속적인 관계를 고려하여 테이블을 무손실 분해하는 과정이다. 1124 | 1125 | > 1NF, 2NF, 3NF, BCNF, 4NF, 5NF, 6NF까지 총 7개의 정규형이 있다. 1126 | 1127 | 비공식적으로는 3NF가 되었으면 정규화되었다고 말할 수 있으며, 실제 현업에서도 제 3NF 정도까지만 수행하고 속도, 튜딩 등 필요에 따라 비정규화(Denormalization) 과정을 수행하기도 한다. 1128 | 1129 | 1130 |
1131 | 1132 |
1133 | 1134 | ### 함수적 종속(Functional Dependency) 1135 | 1136 | 어떤 릴레이션 R이 있고 X, Y는 각각 그 부분집합이다. 이 때 X의 값을 알면 Y를 바로 식별할 수 있다면 Y는 X에 **함수적 종속**이고 X를 결정자, Y를 종속자라고 부른다. 1137 | 1138 | > ex) X : (학번, 수강과목) -> Y : (성적, 이름, 학부, 등록금), X : (학번) -> Y : (이름, 학부, 등록금) 1139 | 1140 |
1141 | 1142 |

1143 |

1144 | 1145 | 1146 | 1147 | 1148 | 1. #### 완전 함수적 종속 1149 | 1150 | 결정자 X, 종속자 Y가 있을 때 Y가 X의 일부에는 함수적 종속이지 않은 관계 1151 | 1152 | > ex) X : (학번, 수강과목) -> Y1 : (성적), Y2: (이름, 학부) 1153 | > 1154 | > Y1 성적은 X의 일부인 학번, 수강과목 각각에 대해서는 종속적이지 않다. 완전함수종속 O 1155 | > 1156 | > 반면, Y2 (이름, 학부)는 X의 일부인 (학번)에 대해서도 종속적이다. 완전함수종속 X 1157 | 1158 | 1159 | 1160 | 2. #### 부분 함수적 종속 1161 | 1162 | Y가 X에 종속이면서 X의 일부에도 함수적 종속인 관계 1163 | 1164 | > 위 예에서 Y2는 X에 부분 함수적 종속이다. 1165 | 1166 | 1167 | 1168 | 3. #### 이행적 함수 종속 1169 | 1170 | X, Y, Z 3개의 속성 집합이 있다. Y가 X에 종속이고 Z가 Y에 종속 즉, X -> Y이고 Y -> Z인 관계를 가질 때 X -> Z인 관계도 성립한다. 이 때 Z는 X에 이행 함수적 종속이다. 1171 | 1172 | > ex) X : (학번), Y : (학부), Z : (등록금) 이 때 (학번) -> (학부) -> (등록금)의 관계를 가지므로 Z는 X에 이행 함수적 종속이다. 1173 | 1174 | 1175 |
1176 |
1177 | 1178 | 1179 | 1180 | ### 제 1정규형(1NF) 1181 | 1182 | 모든 속성의 도메인이 원자값만으로 되어 있는 정규형이다. 테이블의 **모든 속성값들은 반드시 하나의 값만** 가져야 한다. 1183 | 1184 |
1185 | 1186 |

1187 |

1188 | 1189 | 1190 | 위 테이블에서 수강과목 값이 여러 개를 포함하는 튜플이 존재하므로 이를 각각 분리하여 저장한다. 1191 | 1192 | 1NF를 만족하더라도 데이터 이상은 여전히 발생할 수 있다. 1193 | 1194 |
1195 |
1196 | 1197 | ### 제 2정규형(2NF) 1198 | 1199 | 테이블이 1NF를 만족하고, 기본키(Primary Key)를 제외한 **모든 속성이 기본키에 대해 완전 함수적 종속을 만족하는** 정규형이다. 1200 | 1201 |
1202 | 1203 |

1204 |

1205 | 1206 | 1207 | 1208 | 위 테이블에서 (이름, 학부, 등록금) 속성은 기본키 (학번, 수강과목)의 일부인 (학번)에도 종속이므로 부분 함수적 종속인 관계이다. 이때 테이블을 쪼갬으로써 부분 함수적 종속을 제거할 수 있다. 1209 | 1210 | 2NF를 만족하더라도 데이터 이상은 여전히 발생할 수 있다. 1211 | 1212 |
1213 |
1214 | 1215 | 1216 | ### 제 3정규형(3NF) 1217 | 1218 | 테이블이 2NF를 만족하고 기본키(Primary Key)를 제외한 **모든 속성이 기본키에 대해 이행 함수적 종속을 만족하지 않는** 정규형이다. 1219 | 1220 |
1221 | 1222 |

1223 |

1224 | 1225 | 1226 | 1227 | 위 테이블에서 (학번) -> (이름, 학부), (학부) -> (등록금) 관계를 만족하므로 (등록금) 속성은 기본키에 대해 이행 함수적 종속을 만족한다. 이때 테이블을 쪼갬으로써 이행 함수적 종속을 제거할 수 있다. 1228 | 1229 | --- 1230 | 1231 |
1232 | 1233 | 1234 | 1235 | # 인덱스 1236 | 1237 | ## 정의 1238 | 테이블에 대한 동작속도를 높이는 기술로 데이터베이스 조회 기능 성능을 높인다. 1239 | 1240 | 인덱스를 이용하면 Full Scan과 Table Scan을 줄이거나 없애서 속도를 높인다. 1241 | 1242 | Full Scan 시 시간복잡도 - O(N) 1243 | 1244 | 인덱스 사용 시 시간복잡도 - O(logN) 1245 | 1246 | 테이블의 컬럼의 색인화가 일어나서 인덱스를 관리하는 파일(MYI)에서 따로 컬럼을 관리한다. 1247 | 1248 | > ### 테이블 생성 시, 3개의 파일이 만들어진다. 1249 | > - MYI: 인덱스 관리 파일 1250 | > - MYD: 실제 데이터 관리 파일 1251 | > - FRM: 테이블 구조에 관한 파일 1252 | > 1253 | > 인덱스를 생성하지 않으면 MYI는 빈 파일(empty)이다. 1254 | > 1255 | > MYI는 Key-RowId의 구조를 가진다. 1256 | > 1257 | > - Key: 인덱스로 생성한 컬럼의 값 1258 | > - RowId: 데이터가 저장된 주소 값 1259 | 1260 | ## 인덱스를 사용하면 좋을 상황 1261 | 1262 | - SELECT와 Join이 잦은 경우 1263 | - 테이블의 데이터가 많은 경우 1264 | - SELECT를 제외한 DML(=변경)이 잘 일어나지 않는 테이블 1265 | 1266 | ## DML이 일어날 때 인덱스의 변화 1267 | 1268 | ### 1. INSERT 1269 | 1270 | 데이터 추가 시, 새로운 인덱스 추가 1271 | 1272 | ### 2. DELETE 1273 | 1274 | 데이터 삭제 시, 해당 인덱스가 삭제되는 대신 사용하지 않는다는 표시를 남긴다. 1275 | 1276 | -> Table의 레코드 개수와 Index 개수가 달라진다. 1277 | 1278 | ### 3. Update 1279 | 1280 | DELETE + INSERT 1281 | 1282 | UPDATE 기능이 따로 있지 않고 DELETE 수행 후 INSERT가 일어난다. 1283 | 1284 | -> 작업이 두 번 일어난다. 1285 | 1286 | ## 인덱스 생성 1287 | ```MySQL 1288 | -- 생성 방식 2가지 1289 | -- CREATE 이용 1290 | CREATE INDEX 인덱스명 ON 테이블명(컬럼명); 1291 | 1292 | -- ALTER 이용 1293 | ALTER TABLE 테이블명 ADD INDEX 인덱스명(컬럼명); 1294 | ``` 1295 | 1296 | ## 인덱스 조회 1297 | ```MySQL 1298 | SHOW INDEX FROM 테이블명; 1299 | ``` 1300 | 1301 | ## 인덱스 삭제 1302 | ```MySQL 1303 | ALTER TABLE 테이블명 DROP INDEX 인덱스명(컬럼명); 1304 | ``` 1305 | ## 장점 1306 | 1307 | 인덱스 파일은 항상 정렬된 상태이다. 1308 | 1309 | 1) 원하는 데이터를 찾기 위해 테이블을 검색하는 작업을 줄이거나 없앨 수 있다. 1310 | 2) 색인화된 인덱스 파일 검색으로 검색 속도를 향상시킨다. 1311 | 1312 | > ### 색인화 1313 | > 특정 내용이 들어있는 정보를 쉽게 찾아볼 수 있도록 표지를 넣거나 일정한 순서에 따라 배열한 것 1314 | 1315 | ## 단점 1316 | 1317 | 테이블에 새로운 데이터를 추가하거나 갱신, 삭제가 자주 일어나면 좋지 않다. 1318 | 1319 | 테이블에 들어있는 데이터에만 변화가 있는 게 아니라 인덱스에도 추가, 갱신이 일어나기 때문에 오버헤드가 발생할 수 있다. 1320 | 1321 |
1322 |
1323 | 1324 | 1325 | # 트랜잭션 1326 | ## 트랜잭션이란? 1327 | 1328 | **데이터 베이스의 상태를 변경하는 하나의 논리적 기능을 수행하기 위한 작업의 단위**입니다. 쉽게 말해 한꺼번에 수행되어야 할 연산을 모아놓은 것이라고 할 수 있습니다. 데이터 베이스는 항상 정확하고 일관된 데이터를 유지해야하는데 트랜잭션은 이러한 성질을 유지할 수 있게 도와주는 역할을 합니다. 1329 | 1330 | 트랜잭션은 DB 서버에 여러 개의 클라이언트가 동시에 액세스 하거나 응용프로그램이 갱신을 처리하는 과정에서 중단될 수 있는 경우 등 데이터 부정합을 방지하고자 할 때 사용합니다. 부정합이 발생하지 않으려면 프로세스를 병렬로 처리하지 않도록 하여 한 번에 하나의 프로세스만 처리하도록 하면 되는데, 이는 효율이 너무 떨어집니다. 즉, 병렬로 처리할 수 밖에 없는 현실적인 상황으로 인해 부정합을 방지하고자 트랜잭션을 사용하는 것입니다. 1331 | 1332 | 트랜잭션의 중요성은 금융 소프트웨어에서 두드러지게 나타납니다. 예를 들어 A가 B에게 100만원을 송금한다고 합시다. 이러한 작업은 다음과 같은 순서로 이루어 집니다. 1333 | 1334 | 1. A의 계좌에서 100만원을 뺀다. 1335 | 2. B의 계좌에 100만원을 더한다. 1336 | 1337 | 이때 1번 작업이 완료된 후 2번작업이 시작되기 전에 오류가 발생하여 시스템이 멈추게 된다면 100만원이 증발해버리는 일이 발생합니다. 따라서 이러한 작업을 수행할때는 1,2번 작업을 트랜잭션으로 묶어서 한번에 1,2번 작업이 처리되거나 오류가 발생하면 진행했던 모든 작업을 되돌려야 합니다. 1338 | 1339 | ## 트랜잭션의 특성 1340 | 1341 | 트랜잭션이 성공적으로 처리되어 데이터베이스의 무결성과 일관성을 보장하려면 4가지 특성을 만족해야 합니다. 트랜잭션의 특성을 흔히 ACID라고 합니다. 1342 | 1343 | - **Atomicity (원자성)** 1344 | - **Consistency (일관성)** 1345 | - **Isolation (격리성)** 1346 | - **Durability (지속성)** 1347 | 1348 | 1. **Atomic (원자성)** 1349 | - 트랜잭션을 구성하는 연산들은 데이터베이스에 모두 반영되거나 반영되지 않아야함을 의미.(all or nothing) 1350 | - 트랜잭션 수행과정에서 오류가 발생하여 작업이 완료되지 못하면 트랜잭션 시작전 상태로 데이터베이스를 되돌려야 함. 1351 | 2. **Consistency (일관성)** 1352 | - 트랜잭션이 성공적으로 수행된 후에도 데이터베이스가 일관성 있는 상태를 유지해야함을 의미 1353 | - 시스템이 가지고 있는 고정요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 함. 1354 | - 데이터베이스의 제약조건을 위배하는 작업을 트랜잭션과정에서 수행할 수 없음을 나타냄 1355 | - 예시: 송금 예제에서 금액의 데이터 타입을 정수형(integer)에서 문자열(string)로 변경할 수 없음 1356 | 3. **Isolation (격리성)** 1357 | - 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 현재 수행중인 트랜잭션 실행 도중 다른 트랜잭션의 연산이 끼어들 수 없음을 의미 1358 | - 예시: A->B로 송금 과정에서 다른 트랜잭션이 B에게로 송금할 수 없음 1359 | 4. **Durability (지속성)** 1360 | - 트랜잭션이 성공적으로 완료된 이후 데이터베이스에 반영한 수행 결과는 손실되지 않고 영구적으로 유지되어야 함을 의미 1361 | 1362 | - +추가: ACID는 이론적으로 트랜잭션이 보장해야할 특성입니다. 실제로는 모든 규칙을 지킬 경우 성능상 속도 저하가 생길 수 있어 트랜잭션 격리 수준을 조정합니다. 1363 | 1364 | ## 트랜잭션의 연산 1365 | 1366 | **1. COMMIT 연산** 1367 | 1368 | - **트랜잭션이 성공적으로 수행되었음을 선언하는 연산** 1369 | - commit 연산의 실행을 통해 트랜잭션의 수행이 성공적으로 완료되었음을 선언하고 결과를 최종 데이터베이스에 반영. 1370 | 1371 | **2. ROLLBACK 연산** 1372 | 1373 | - **트랜잭션이 수행을 실패했음을 선언하고 작업울 취소하는 연산** 1374 | - 트랜잭션 수행되는 도중 일부 연산이 처리되지 못한 상황에서는 rollback 연산을 실행하여 트랜잭션의 수행이 실패했음을 선언하고, 데이터베이스를 트랜잭션 수행 전의 일관된 상태로 되돌려야 함. 1375 | 1376 | ## 트랜잭션의 상태 1377 | 1378 | ![image](https://itwiki.kr/images/1/1e/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98_%EC%83%81%ED%83%9C%EC%A0%84%EC%9D%B4%EB%8F%84.png) 1379 | 1380 | - 활동 상태 1381 | - 트랜잭션이 수행을 시작하여 현재 수행 중인 상태. 1382 | - 부분 완료 상태 1383 | - 트랜잭션의 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태 1384 | - 완료 상태 1385 | - 트랜잭션이 성공적으로 완료되어 commit 연산을 실행한 완료 상태. 1386 | - 실패 상태 1387 | - 장애가 발생하여 트랜잭션의 수행이 중단된 상태. 1388 | - 철회 상태 1389 | - 수행이 실패하여 rollback 연산을 실행한 상태. 1390 | 1391 | ## 병행제어 1392 | 병행제어란 여러개의 트랜잭션이 실행될 때 트랜잭션들이 데이터베이스의 일관성을 파괴하지 않고 다른 트랜잭션에 영향을 주지 않으면서 트랜잭션을 제어하는 것을 의미합니다. 1393 | 1394 | ### 병행 실행시 발생 가능한 문제들 1395 | - **분실된 갱신**: 두 개의 트랜잭션이 같은 데이터에 대해서 동시에 갱신 작업을 하면 하나의 갱신 작업이 분실되는 경 1396 | - **모순성**: 한 개의 트랜잭션 작업이 갱신 작업을 하고 있는 상태에서 또 하나의 트랜잭션이 같은 작업 구역에 침범하여 작업하게 되어 데이터베이스의 일관성을 해치는 경우 1397 | - **연쇄복귀**: 같은 자원을 사용하는 두개의 트랜잭션 중 한 개의 트랜잭션이 성공적으로 일을 수행하였다 하더라도 다른 트랜잭션이 처리하는 과정에서 실패하게 되면 두 개의 트랜잭션 모두가 복귀되는 현상 1398 | - **비완료 의존성**: 한 개의 트랜잭션이 수행과정에서 실패하였을 때, 이 트랜잭션이 회복되기 전에 다른 트랜잭션이 수행 결과를 참조하는 현상 1399 | 1400 | ### 병행제어 기법 1401 | 1. 로킹(Locking) 1402 | 1403 | 트랜잭션이 어떤 데이터에 접근하고자 할 때 로킹을 수행하며 로킹을 한 트랜잭션만이 로킹을 해제할 수 있음. 트랜잭션은 로킹이 된 데이터에 대해서만 연산을 수행할 수 있으며 로킹의 단위에는 필드, 레코드, 파일, 데이터베이스 모두 로킹이 될 수 있음 1404 | 1405 | - 로킹 단위가 크면 : 관리하기가 용이(로킹 오버헤드 감소), 하지만 동시성 수준이 낮아짐 1406 | - 로킹 단위가 작으면 : 동시성 수준이 높아지지만 관리가 까다로움(로킹 오버헤드 증가) 1407 | 1408 | - 2단계 로킹 규약(Two-Phase Locking Protocol) 1409 | Lock과 Unlock이 동시에 이루어지면 일관성이 보장되지 않으므로 Lock만 가능한 단계와 Unlock만 가능한 단계를 구분하며 직렬가능성을 보장함, 하지만 교착상태가 발생할 수 있음. 1410 | - 확장단계 : 트랜잭션이 Lock만 할 수 있고 Unlock은 할 수 없음 1411 | - 축소단계 : 트랜잭션이 Unlock만 할 수 있고 Lock은 할 수 없음 1412 | - 예시) T1 : write(A) read(B), T2 : read(B) write(A) => dead lock 발생! 1413 | 1414 | - 로킹의 종류 1415 | - S-lock(공유잠금) 1416 | - 공유잠금을 설정한 트랜잭션은 데이터 항목에 대해 읽기 연산(read)만 가능 1417 | - 하나의 데이터 항목에 대해 여러 개의 공유잠금이(S-lock) 가능 1418 | - 다른 트랜잭션도 읽기 연산(read) 만을 실행 1419 | - X-lock(배타잠금): 1420 | - 배타잠금을 설정한 트랜잭션은 데이터 항목에 대해서 읽기 연산(read)과 쓰기 연산(write) 모두 가능 1421 | - 하나의 데이터 항목에 대해서는 하나의 배타잠금(X-lock)만 가능 1422 | - 다른 트랜잭션은 읽기 연산(read)와 쓰기 연산(write) 모두 불가능 1423 | 1424 | 2. 타임스탬프(Time Stamp) 1425 | 데이터에 접근하는 시간을 미리 정하여 정해진 시간의 순서대로 데이터에 접근하며 수행함, 직렬가능성을 보장하며 시간을 나눠 사용하기 때문에교착상태가 발생하지 않음, 하지만 연쇄복귀를 초래할 수 있음. 1426 | 1427 | 3. 낙관적 병행제어(Optimistic Concurrency Control) 1428 | 트랜잭션 수행 동안은 어떠한 검사도 하지 않고, 트랜잭션 종료 시에 일괄적으로 검사함, 트랜잭션 수행 동안 그 트랜잭션을 위해 유지되는 데이터 항복의 지역사본에 대해서만 갱신하며 트랜잭션 종료 시에 동시성을 위한 트랜잭션 직렬화가 검증되면 일시에 DB로 반영함 1429 | 1430 | 4. 다중 버전 병행제어(Multi-version Concurrency Control) 1431 | 하나의 데이터 아이템에 대해 여러 버전의 값을 유지하며 조회성능을 최대한 유지하기 위한 기법, 트랜잭션 간의 충돌 문제는 대기가 아니라 복귀처리 함으로 연쇄복귀초래 발생 가능성이 있음 1432 |
1433 | 1434 | # 트랜잭션 격리수준 1435 | ## 트랜잭션 격리수준(isolation level)이란? 1436 | 트랜잭션의 네 가지 주요 성질인 원자성, 일관성, 고립성, 내구성 (ACID) 중 **고립성(isolation)** 을 구현하는 개념이다. 1437 | 1438 | * 고립성은 한 트랜잭션에서 데이터가 수정되는 과정이 다른 트랜잭션과는 독립적으로 진행되어야 한다는 특성이다. 1439 | 1440 | **트랜잭션 격리수준(isolation level)** 이란 동시에 여러 트랜잭션이 처리될 때, 트랜잭션끼리 얼마나 서로 고립되어 있는지를 나타내는 것이다. 1441 | 1442 | 즉, 간단하게 말해 특정 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것이다. 1443 | 1444 |
1445 | 1446 | 격리수준은 크게 아래의 4개로 나뉜다. 1447 | 1448 | * READ UNCOMMITTED 1449 | * READ COMMITTED 1450 | * REPEATABLE READ 1451 | * SERIALIZABLE 1452 | 1453 |
1454 | 1455 | 아래로 내려갈수록 트랜잭션 간 고립 정도가 높아지며, 성능이 떨어지는 것이 일반적이다. 1456 | 1457 | 일반적인 온라인 서비스에서는 `READ COMMITTED`나 `REPEATABLE READ` 중 하나를 사용한다. 1458 | 1459 | (oracle의 기본 격리수준 = READ COMMITTED, mysql의 기본 격리수준 = REPEATABLE READ) 1460 | 1461 |
1462 | 1463 | ## 트랜잭션 격리수준의 종류 1464 | ### READ UNCOMMITTED (레벨 0) - 커밋되지 않는 읽기 1465 | * 각 트랜잭션에서의 변경 내용이 `COMMIT`이나 `ROLLBACK` 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있다. 1466 | * 정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장한다. 1467 | * 아래의 그림과 같이 Commit이 되지 않는 상태지만 Update된 값을 다른 트랜잭션에서 읽을 수 있다. 1468 | 1469 |

1470 | 1471 |

1472 | 1473 | * **DIRTY READ** 현상 발생 1474 | * 트랜잭션이 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상 1475 | 1476 |
1477 | 1478 | ### READ COMMITTED (레벨 1) - 커밋된 읽기 1479 | * RDB에서 대부분 기본적으로 사용되고 있는 격리 수준이다. 1480 | * `Dirty Read`와 같은 현상은 발생하지 않는다. 1481 | * 실제 테이블 값을 가져오는 것이 아니라 **Undo 영역에 백업된 레코드**에서 값을 가져온다. 1482 | 1483 |

1484 | 1485 |

1486 | 1487 |
1488 | 1489 | * **Non-repeatable read** 현상 발생 1490 | * 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때 그 사이에 다른 트랜잭션 값을 수정 또는 삭제하면서 두 쿼리의 결과가 상이하게 나타나는 일관성이 깨진 현상 1491 | 1492 |

1493 | 1494 |

1495 | 1496 |
1497 | 1498 | ### REPEATABLE READ (레벨 2) - 반복가능한 읽기 1499 | * MySQL에서는 트랜잭션마다 `트랜잭션 ID`를 부여하여 **트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것**만 읽게 된다. 1500 | * **Undo 공간에 백업해두고 실제 레코드 값을 변경**한다. 1501 | * 백업된 데이터는 불필요하다고 판단하는 시점에 주기적으로 삭제한다. 1502 | * Undo에 백업된 레코드가 많아지면 MySQL 서버의 처리 성능이 떨어질 수 있다. 1503 | * 이러한 변경방식은 `MVCC(Multi Version Concurrency Control)`라고 부른다. 1504 | 1505 |

1506 | 1507 |

1508 | 1509 | * **PHANTOM READ** 현상 발생 1510 | * 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상 1511 | * `REPETABLE READ`에 의하면 원래 출력되지 않아야 하는데 **UPDATE** 문의 영향을 받은 후 부터 출력된다. 1512 | * 이를 방지하기 위해서는 쓰기 잠금을 걸어야 한다. 1513 | 1514 |

1515 | 1516 |

1517 | 1518 |
1519 | 1520 | ### SERIALIZABLE (레벨 3) - 직렬화 가능 1521 | * 가장 단순한 격리 수준이지만 가장 엄격한 격리 수준으로 **완벽한 읽기 일관성 모드**를 제공한다. 1522 | * 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 **수정 및 입력 불가능** 1523 | * 성능 측면에서는 동시 처리성능이 가장 낮다. 1524 | * SERIALIZABLE에서는 `PHANTOM READ`가 발생하지 않는다. 하지만 데이터베이스에서 거의 사용되지 않는다. 1525 | 1526 |
1527 | 1528 | ## 낮은 격리수준을 활용했을 때 발생하는 현상들 1529 | 이 현상들은 트랜잭션의 고립성과 데이터의 무결성의 지표로 사용된다. 1530 | 1531 | 1. **더티 리드 (Dirty read)** : 생성, 갱신, 혹은 삭제 중에 커밋 되지 않은 데이터 조회를 허용함으로써, 트랜잭션이 종료되면 더 이상 존재하지 않거나, 롤백되었거나, 저장 위치가 바뀌었을 수도 있는 데이터를 읽어들이는 현상이다. 1532 | 2. **반복 가능하지 않은 조회 (Non-repeatable read)** : 한 트랜잭션 내에서 같은 행이 두 번 이상 조회됐는데 그 값이 다른 경우를 가리킨다. (A와 B가 마지막 남은 영화표를 예매하는데 A가 고민하는 중에 B가 표를 구매하여 A는 상반된 정보를 받게 되는 경우 등) 1533 | 3. **팬텀 리드 (Phantom read)** : 한 트랜잭션 내에서 같은 쿼리문이 실행되었음에도 불구하고 조회 결과가 다른 경우를 뜻한다. 1534 | 1535 |

1536 | 1537 |

1538 | 1539 |
1540 | 1541 | ---- 1542 | 1543 | # 레디스 1544 | 1545 | ## 레디스란? 1546 | 1547 | - 인 메모리 데이터베이스로 메모리에 위치하고 있는 데이터베이스이다. 1548 | 1549 | - 비관계형 데이터베이스(NoSQL)로 비정형 데이터를 저장한다. 1550 | 1551 | - Key와 Value의 구조로 데이터를 저장한다. 1552 | 1553 | - 문자열, Hash, List, Set, Sorted Set 총 5가지의 데이터 형을 지원한다. 1554 | 1555 | ## 레디스는 어디에 사용할까? 1556 | 1557 | 1. 데이터 캐싱 1558 | 2. 메시지 브로커 1559 | 1560 | ### 데이터 캐싱 1561 | 1562 | 데이터베이스에 접근하지 않고 빠르게 접근할 수 있는 저장 공간에 데이터를 저장해둠으로써 빠른 Read와 Write를 가능하게 하는 방법 1563 | 1564 | ### 데이터 캐싱에 적합한 데이터 1565 | 1566 | > 1) 자주 조회하는 데이터 1567 | > 1568 | > 2) 업데이트가 잘 일어나지 않는 데이터 1569 | > 1570 | > 3) 반복적으로 자주 요청이 들어오며 동일한 결과를 리턴하는 기능의 결과값 1571 | 1572 | ### 메시지 브로커 1573 | 1574 | Pub & Sub 패턴에서 Publisher가 발행한 메시지를 Subscriber에게 전달해주는 역할 1575 | 1576 | ## 레디스의 데이터 영속성 1577 | 1578 | ### 영속성이란? 1579 | 1580 | 영원히 사라지지 않는 데이터의 특성, 데이터를 생성하고 변경하던 프로그램이 종료되어도 데이터가 사라지지 않는다. 1581 | 1582 | 레디스는 메모리(휘발성)에 데이터베이스가 위치하기 때문에 갑작스러운 종료에 대비하기 위한 방법이 있다. 1583 | 1584 | 1. RDB 방식 1585 | 2. AOF 방식 1586 | 1587 | ### RDB 방식 1588 | > 1589 | >RDB란 .rdb 라는 파일 확장자 형태로 메모리에 있는 내용을 **스냅샷** 형태로 저장하는 방식이다. 1590 | > 1591 | >스냅샷(Snapshot)이란 한 순간의 메모리에 있는 내용을 저장하는 것이다. 1592 | > 1593 | >스냅샷은 일정 간격마다 뜨게 된다. 1594 | > 1595 | >장점 1596 | >- 메모리의 Snapshot을 뜨게 되면 서버가 꺼지고(stop or down) 재실행(restart) 시에 Snapshot을 load만 하면 되기 때문에 재실행(restart) 시간이 빠르다. 1597 | > 1598 | >단점 1599 | > 1600 | >- Snapshot을 뜨고 시간이 흐른 후 서버가 꺼지게 되면 Snapshot 이후의 데이터는 복구할 수 없다. 1601 | 1602 | 1603 | ### AOF 방식 1604 | > 1605 | >AOF란 Append Only File을 뜻하며 write와 update와 같은 쓰기 명령을 모두 log 파일에 저장하는 형태이다. 1606 | > 1607 | >서버가 꺼지고 재실행하는 경우 log 파일에 저장된 명령들이 순차적으로 실행하며 데이터를 복구한다. 1608 | > 1609 | >장점 1610 | >- RDB의 문제점인 Snapshot 이후의 데이터 유실을 보완할 수 있다. 1611 | > 1612 | >단점 1613 | > 1614 | >- log 파일의 명령을 다시 실행해야 하기 때문에 서버 재실행 시간이 느리다. 1615 | 1616 | --- 1617 | 1618 | # Hint 1619 | 1620 | 아래 Hint에 대한 모든 내용들은 `MySQL`을 기준으로 작성되었음. 1621 | 1622 | 힌트는 옵티마이저의 실행 계획을 원하는대로 바꿀 수 있게 해준다.
1623 | 옵티마이저라고 반드시 최선의 실행계획을 수립할 수는 없기 때문에, 조인이나 인덱스의 잘못된 실행 계획을 개발자가 직접 바꿀 수 있도록 도와주는 것이 힌트이다. 1624 | 1625 | 힌트의 문법이 올바르더라도 힌트가 반드시 받아 들여지는 것은 아니며, 옵티마이저에 의해 선택되지 않을 수도 있고 선택될 수도 있다. 1626 | 1627 | Hint는 크게 2가지로 구분할 수 있다. 1628 | 1. `옵티마이저 힌트` 1629 | 2. `인덱스 힌트` 1630 | 1631 | `옵티마이저 힌트`와 `인덱스 힌트`는 서로 다르며, 함께 사용할 수도 있고 별도로 사용할 수도 있다. 1632 | 1633 | ## 옵티마이저 힌트 1634 | 1635 | 옵티마이저를 제어하는 방법 중 하나는, optimizer_switch 시스템 변수를 설정하는 것 이다. 이는 모든 후속 쿼리 실행에 영향을 주기 때문에, 일반적인 사용자들에게는 권장되지 않은 방법이다. 1636 | 1637 | 그래서 옵티마이저를 더 세밀하게 선택적으로 제어해야 할 땐, 옵티마이저 제어를 원하는 부분을 지정할 수 있는 옵티마이저 힌트를 사용하는 것이다.
1638 | 즉, 명령문의 한 테이블에 대한 최적화를 활성화하고 다른 테이블에 대한 최적화를 비활성화할 수 있다.
1639 | 명령문 내의 옵티마이저 힌트는 optimizer_switch 보다 우선시 되어 적용된다. 1640 | 1641 | 옵티마이저 힌트는 다양한 범위 수준에서 적용된다. 1642 | 1643 | - `전역`: 힌트가 전체 문에 영향을 줌 1644 | - `쿼리 블록`: 힌트가 명령문 내의 특정 쿼리 블록에만 영향을 줌 1645 | - `테이블`: 힌트가 쿼리 블록 내의 특정 테이블에민 영향을 줌 1646 | - `인덱스`: 힌트가 테이블 내의 특정 인덱스에만 영향을 줌 1647 | 1648 | ### 사용 방법 1649 | 옵티마이저 힌트는 /*+ .... */주석 내에 지정해야 한다. 1650 | 1651 | |힌트 명|힌트 설명|적용 범위 수준| 1652 | |:----------------------------:|:------------------------------------------:|:---------------------:| 1653 | | BKA, NO_BKA | 일괄 처리된 키 액세스 조인 처리에 영향| 쿼리 블록, 테이블 | 1654 | | BNL, NO_BNL | MySQL 8.0.20 이전: 블록 중첩-루프 조인 처리, MySQL 8.0.18 이상: 해시 조인 최적화, MySQL 8.0.20 이상: 해시 조인 최적화에만 영향 | 쿼리 블록, 테이블 | 1655 | | DERIVED_CONDITION_PUSHDOWN, NO_DERIVED_CONDITION_PUSHDOWN | 구체화된 파생 테이블에 대한 파생 조건 푸시다운 최적화 사용 또는 무시(MySQL 8.0.22에 추가) | 쿼리 블록, 테이블| 1656 | | GROUP_INDEX, NO_GROUP_INDEX | GROUP BY 작업(MySQL 8.0.20에 추가)에서 인덱스 검색에 대해 지정된 인덱스를 사용하거나 무시 | 인덱스 | 1657 | | HASH_JOIN, NO_HASH_JOIN | 해시 조인 최적화에 영향 (MySQL8.0.18만 해당)| 쿼리 블록, 테이블| 1658 | | INDEX, NO_INDEX | JOIN_INDEX, GROUP_INDEX 및 ORDER_INDEX의 조합으로 작동하거나 NO_JOIN_INDEX, NO_GROUP_INDEX 및 NO_ORDER_INDEX(MySQL 8.0.20에 추가)의 조합으로 작동| 인덱스 | 1659 | | INDEX_MERGE, NO_INDEX_MERGE | 인덱스 병합 최적화에 영향| 테이블, 인덱스 | 1660 | | JOIN_INDEX, NO_JOIN_INDEX | 모든 액세스 방법에 대해 지정된 인덱스 또는 인덱스를 사용하거나 무시(MySQL 8.0.20에 추가) | 인덱스 | 1661 | | JOIN_FIXED_ORDER | FROM절에 지정된 순서대로(FIXED) 테이블을 조인하도록 지시 | 쿼리 블록 | 1662 | | JOIN_ORDER | 가능하다면 힌트에 지정된 순서대로 조인하도록 지시| 쿼리 블록| 1663 | | JOIN_PREFIX | 가장 먼저 조인을 시작 할 테이블 지정 | 쿼리 블록| 1664 | | JOIN_SUFFIX | 가장 마지막으로 조인 할 테이블 지정 | 쿼리 블록| 1665 | | MAX_EXECUTION_TIME | 구문 실행 시간 제한| 전역 범위| 1666 | | MERGE, NO_MERGE | 외부 쿼리 블록으로 병합되는 파생 테이블/뷰에 영향 | 테이블| 1667 | | MRR, NO_MRR | 다중 범위 읽기 최적화에 영향| 테이블, 인덱스| 1668 | | NO_ICP | 인덱스 조건 푸시다운 최적화에 영향| 테이블, 인덱스| 1669 | | NO_RANGE_OPTIMIZATION | 범위 최적화에 영향| 테이블, 인덱스| 1670 | | ORDER_INDEX, NO_ORDER_INDEX | 행을 정렬하기 위해 지정된 인덱스 또는 인덱스 사용하거나 또는 무시(MySQL 8.0.20에 추가) | 인덱스 | 1671 | | QB_NAME | 쿼리 블록에 이름 할당 |쿼리 블록| 1672 | | RESOURCE_GROUP | 구문을 실행하는 동안 리소스 그룹 설정 | 전역 범위| 1673 | | SEMIJOIN, NO_SEMIJOIN | Semijoin 전략에 영향, MySQL 8.0.17부터는 anti조인에도 적용 | 쿼리 블록 | 1674 | | SKIP_SCAN, NO_SKIP_SCAN | 스킵 검색 최적화에 영향| 테이블, 인덱스| 1675 | | SET_VAR | 구문을 실행하는 동안 변수 설정| 전역 범위| 1676 | | SUBQUERY | 구체화에 영향, IN-to-EXISTS 하위 쿼리 전략| 쿼리 블록| 1677 | 1678 | ```sql 1679 | /*+ BKA(table1) */ 1680 | 1681 | /*+ BNL(table1, table2) */ 1682 | 1683 | /*+ NO_RANGE_OPTIMIZATION(table3 PRIMARY) */ 1684 | 1685 | /*+ QB_NAME(queryblock1) */ 1686 | 1687 | SELECT /*+ BNL(t1) BKA(t2) */ ... 1688 | // 하나의 쿼리 블록에서 여러 힌트를 사용할 땐, 하나의 힌트 주석안에 여러개의 힌트를 선언하여 사용해야 한다. 1689 | // 즉, SELECT /*+ BNL(t1) */ /* BKA(t2) */ ... 는 안됨. 1690 | ``` 1691 | 1692 | 옵티마이저 힌트는 SELECT, UPDATE, INSERT, REPLACE, DELETE문에서 아래와 같이 사용할 수 있다. 1693 | 1694 | ```sql 1695 | SELECT /*+ HINT */ ... 1696 | INSERT /*+ HINT */ ... 1697 | REPLACE /*+ HINT */ ... 1698 | UPDATE /*+ HINT */ ... 1699 | DELETE /*+ HINT */ ... 1700 | ``` 1701 | 1702 | 그리고 아래와 같이 쿼리 블록으로 구분하여 사용이 가능하다. 1703 | ```sql 1704 | (SELECT /*+ ... */ ... ) 1705 | (SELECT ... ) UNION (SELECT /*+ ... */ ... ) 1706 | (SELECT /*+ ... */ ... ) UNION (SELECT /*+ ... */ ... ) 1707 | UPDATE ... WHERE x IN (SELECT /*+ ... */ ...) 1708 | INSERT ... SELECT /*+ ... */ ... 1709 | ``` 1710 | 1711 | ## 조인 순서 최적화 힌트 1712 | MySQL 8.0은 이전 버전보다 훨씬 강력하고 편의성이 강한 Optimizer hint를 제공한다.
1713 | 그 중 하나가 조인 순서 최적화 힌트이다. 1714 | 1715 | 조인 순서 최적화 힌트는 옵티마이저가 테이블을 조인하는 순서에 영향을 준다.
1716 | 기존의 join 순서를 제어하던 STRAIGHT_JOIN 구문등은 사용상의 여러 문제를 만들어 냈지만, 조인 순서 최적화 힌트를통해 그러한 문제를 해결하게 되었다. 1717 | 1718 | ### 사용 방법 1719 | ```sql 1720 | HINT_NAME([@query_block_name]) 1721 | HINT_NAME([@query_block_name] TABLE_NAME [, tbl_name] ...) 1722 | HINT_NAME(TABLE_NAME[@query_block_name] [, TABLE_NAME[@query_block_name]] ...) 1723 | ``` 1724 | 1725 | HINT_NAME에 올 수 있는 조인 순서 최적화 힌트는 4가지가 있다. 1726 | - `JOIN_FIXED_ORDER`: FROM절에 지정된 순서대로(FIXED) 테이블을 조인하도록 지시 (STRAIGHT_JOIN의 힌트화) 1727 | - `JOIN_ORDER`: 가능하다면 힌트에 지정된 순서대로 조인하도록 지시 1728 | - `JOIN_PREFIX`: 가장 먼저 조인을 시작 할 테이블 지정 1729 | - `JOIN_SUFFIX`: 가장 마지막으로 조인 할 테이블 지정 1730 |
1731 | 1732 | 지정한 TABLE_NAME의 모든 테이블에 힌트가 적용되며, TABLE_NAME은 스키마 이름으로 한정할 수 없다.
1733 | TABLE_NAME에 별칭이 있는 경우 힌트는 테이블 이름이 아니라 별칭을 참조해야 한다. 1734 | 1735 | ```sql 1736 | SELECT 1737 | /*+ JOIN_PREFIX(t2, t5@subq2, t4@subq1) 1738 | JOIN_ORDER(t4@subq1, t3) 1739 | JOIN_SUFFIX(t1) */ 1740 | COUNT(*) 1741 | FROM t1 JOIN t2 JOIN t3 1742 | WHERE t1.f1 IN (SELECT /*+ QB_NAME(subq1) */ f1 FROM t4) 1743 | AND t2.f1 IN (SELECT /*+ QB_NAME(subq2) */ f1 FROM t5); 1744 | ``` 1745 | `(SELECT /*+ QB_NAME(subq1) */ f1 FROM t4)` : 쿼리 블록의 이름을 subq1로 지정 1746 | `t4@subq1` : 쿼리 블록 subq1의 테이블 t4를 지정 1747 | 1748 | ```sql 1749 | /*+ JOIN_PREFIX(t2, t5@subq2, t4@subq1) 1750 | JOIN_ORDER(t4@subq1, t3) 1751 | JOIN_SUFFIX(t1) */ 1752 | ``` 1753 | `t2`, `t5@subq2`, `t4@subq1`, `t3`, `t1` 순서대로 조인 1754 | 1755 | ## 인덱스 힌트 1756 | 1757 | Mysql를 사용을 하다보면 복잡한 쿼리의 경우 서로의 인덱스가 물리고 물려서 필요한 인덱스를 안타고 엉뚱한 인덱스를 사용하는 경우가 있다.
1758 | 예를 들어서 A, B, C의 인덱스가 순서대로 사용되어야 하는데 옵티마이저가 B, C, A 순으로 처리를 하여서 속도가 느려지는 경우에 이런 순서를 잡기 위해서 인덱스 힌트를 사용한다.
1759 | 즉, Mysql에서 제공하는 인덱스 힌트를 쓰면 강제적으로 할당한 Index를 이용하여 쿼리가 실행이 된다.
1760 | 하지만 JPA(hibernate)에서 사용이 불가능하기 때문에 JdbcTemplate 등을 이용하여 Native Query로 활용해야 된다. 1761 | 1762 | ### 사용 방법 1763 | ```sql 1764 | TABLE_NAME [[AS] ALIAS] INDEX_HINT INDEX_LIST 1765 | 1766 | INDEX_LIST: 1767 | USE {INDEX|KEY} 1768 | [FOR {JOIN|ORDER BY|GROUP BY}] (INDEX_LIST) 1769 | | IGNORE {INDEX|KEY} 1770 | [FOR {JOIN|ORDER BY|GROUP BY}] (INDEX_LIST) 1771 | | FORCE {INDEX|KEY} 1772 | [FOR {JOIN|ORDER BY|GROUP BY}] (INDEX_LIST) 1773 | 1774 | INDEX_LIST: 1775 | INDEX_NAME , INDEX_NAME ... 1776 | ``` 1777 | 1778 | - `USE 키워드` : 특정 인덱스를 사용하도록 권장 1779 | - `IGNORE 키워드` : 특정 인덱스를 사용하지 않도록 지정 1780 | - `FORCE 키워드` : USE 키워드와 동일한 기능을 하지만, 옵티마이저에게 보다 강하게 해당 인덱스를 사용하도록 권장 1781 | 1782 |
1783 | 1784 | - `USE INDEX FOR JOIN` : JOIN 키워드는 테이블간 조인뿐 아니라 레코드 검색하는 용도까지 포함 1785 | - `USE INDEX FOR ORDER BY` : 명시된 인덱스를 ORDER BY 용도로만 사용하도록 제한 1786 | - `USE INDEX FOR GROUP BY` : 명시된 인덱스를 GROUP BY 용도로만 사용하도록 제한 1787 | 1788 | ```sql 1789 | SELECT * 1790 | FROM TABLE1 1791 | USE INDEX (COL1_INDEX, COL2_INDEX) 1792 | WHERE COL1=1 AND COL2=2 AND COL3=3; 1793 | 1794 | SELECT * 1795 | FROM TABLE2 1796 | IGNORE INDEX (COL1_INDEX) 1797 | WHERE COL1=1 AND COL2=2 AND COL3=3; 1798 | 1799 | SELECT * 1800 | FROM TABLE3 1801 | USE INDEX (COL1_INDEX) 1802 | IGNORE INDEX (COL2_INDEX) FOR ORDER BY 1803 | IGNORE INDEX (COL3_INDEX) FOR GROUP BY 1804 | WHERE COL1=1 AND COL2=2 AND COL3=3; 1805 | ``` 1806 | 1807 | --- 1808 | 1809 | 1810 | 1811 | # 클러스터링(Clustering) 1812 | 1813 | 클러스터링은 여러 개의 DB 서버를 구축하여 **DB 서버를 다중화** 하는 것입니다. 1814 | 1815 | 클러스터링 구조는 DB 서버들 간의 데이터 무결성을 유지하기 위해 **데이터를 동기화**하여 처리합니다. 1816 | 1817 | 그래서 동기화하는 시간이 필요하므로 비동기 방식의 Replciation에 비해 쓰기 성능이 떨어질 수 있습니다. 1818 | 1819 | 데이터를 동기화 하는 방식은 클러스터링 방식과 DB 서비스에 따라 다소 차이가 있습니다. 1820 | 1821 | 클러스터링은 **Fail Over 기능**으로 고가용성(High Availability)을 유지하여 Single point of failure와 같은 문제를 해결할 수 있습니다. 1822 | 1823 | 1824 | 1825 | > Fail Over : 시스템에 문제가 생기면 예비 시스템으로 자동 전환되는 기능 1826 | > 1827 | > Single point of failure(SPOF) : 부분의 문제가 전체 시스템을 정지시켜 버리는 것 1828 | 1829 | 1830 | 1831 | ## 구성 방식 1832 | 1833 | ### Active - Active Clustering 1834 | 1835 |

1836 | 1837 | - Cluster을 이루는 DB 서버들을 모두 Active 상태로 구성합니다. 1838 | - 장점 1839 | 1840 | > - 서버 하나가 중단되도 다른 서버들이 역할을 바로 수행하여 서비스 중단이 거의 없습니다. 1841 | > - 동시에 사용되는 CPU와 메모리가 증가하므로 성능을 향상시킬 수 있습니다. 1842 | > - load balance를 이용한 병렬 처리가 가능합니다. 1843 | 1844 |

1845 | 1846 | 1847 | 1848 | - 단점 1849 | 1850 | > - DB 서버들의 데이터 동기화 구현이 복잡합니다. 1851 | > - 저장소 하나를 공유하면 `병목현상`이 발생할 수 있습니다. 1852 | > 1853 | > - 여러 대의 서버를 동시에 운영하므로 비용이 크게 증가합니다. 1854 | > 1855 | > 병목 현상 : 전체 시스템의 성능이나 용량이 하나의 구성요소로 인해 제한을 받는 현상. 1856 | 1857 | - Cluster들의 상태를 모니터링하는 서버를 따로 둘 수도 있습니다. 1858 | - 대표적인 서비스: Oracle의 RAC(Real Application Cluster) [참고사이트](https://12bme.tistory.com/322) 1859 | 1860 | 1861 | 1862 | ### Active - Standby Clustering 1863 | 1864 | 1865 | 1866 |

1867 | 1868 | - 하나의 DB 서버는 Active 상태, 나머지 서버는 Standby 상태로 구성합니다. 1869 | - Active DB 서버가 다운됐을 때 Standby DB 서버를 Active상태로 전환합니다. 1870 | - Standby DB서버에서 Active DB서버에 신호(Heatbeat 등)를 주기적으로 보내며 시스템 상태를 확인합니다. 1871 | 1872 | - 장점 1873 | 1874 | > - Active - Active에 비해 적은 비용이 듭니다. 1875 | 1876 | - 단점 1877 | 1878 | > - Active 서버가 다운되었을 때 다른 서버가 Active로 전환되는데 시간이 들어서 서버가 중단되는 시간이 있습니다. 1879 | 1880 | - Hot-Standby : Active DB 서버가 다운되기 전에도 DB가 작동되고 있도록 구성합니다. 1881 | - Cold-Standby : 초기 세팅 후에 작동하지 않다가 Active DB 서버가 다운된 시점에 작동하는 구성합니다. 1882 | - Hot-Standby는 Cold-Standby 보다 서버 가동 시간이 짧지만 비용이 더 많이 듭니다. 1883 | 1884 | --- 1885 | 1886 |
1887 | 1888 | # 리플리케이션(Replication) 1889 | 1890 | 리플리케이션은 여러 개의 **DB를 권한에 따라 수직적인(Master-Slave) 구조로 구축**하는 방식입니다. 1891 | 1892 | 리플리케이션 구조는 **데이터를 변경하는 쓰기(Insert, Update, Delete 등) 작업은 Master 가 처리**하고 **읽기(Select) 작업은 Slave가 처리**하도록 합니다. 1893 | 1894 | 리플리케이션 구조는 클러스터와 달리 **비동기적으로 DB 간의 데이터를 동기화**합니다. 그래서 클러스터 구조 보다 데이터의 쓰기 작업의 속도가 빠릅니다. 하지만 비동기적이므로 딜레이 차이로 어떤 DB에는 데이터가 동기화 되어 있지만 그렇지 않은 DB가 존재할 수 있습니다. 1895 | 1896 |

1897 | 1898 | 1899 | 1900 | ## 동작 방식 1901 | 1902 |

1903 | 1904 | 1. Master에 쓰기 트랜잭션이 수행됩니다. 1905 | 2. Master는 데이터를 저장하고 트랜잭션에 대한 Binary log를 만들어 기록합니다. 1906 | 3. Slave는 IO thread를 통해서 Master에 Binary log를 요청합니다. 1907 | 4. Master는 Binary log를 요청 받으면 binlog dump thread를 통해서 로그를 전송합니다. 1908 | 5. IO thread는 전송받은 로그로 Relay log를 만듭니다. 1909 | 6. SQL thread는 Relay log를 읽어서 이벤트를 다시 실행하여 Slave에 데이터를 저장합니다. 1910 | 1911 | 1912 | 1913 | ## 구성 1914 | 1915 | - Master 1916 | 1917 | - **Binary log** 1918 | 1919 | MySQL은 데이터 또는 스키마를 변경하는 이벤트들을 저장할 수 있으며, Binary log 이 이벤트들을 저장한 것입니다. Binary log는 DB를 변경하는 모든 이벤트가 저장되어 있으므로 원하는 시점으로 데이터를 복구할 수 있습니다. 그래서 Slave에서 이를 다시 실행하면 DB를 동기화 할 수 있습니다. 1920 | 1921 | - **Binlog dump thread** 1922 | 1923 | Binlog dump thread는 Slave의 I/O thread로 binary log를 요청했을 때 Master에서 이를 처리하기 위해 만든 쓰레드 입니다. Binlog dump thread는 Slave가 로그를 요청하면 binary log에 lock을 걸고, Slave로 로그를 전송합니다. 이때, binary log를 너무 긴 시간 lock하지 않기 위해서 Slave로 전송하기 전에 binary log를 읽고 바로 락을 해제합니다. binlog dump thread는 Slave가 Master에 connect 할 때 생성되지만, 여러 개의 Slave가 붙어도 단 하나의 스레드만 생성됩니다. 1924 | 1925 | - Slave 1926 | 1927 | - **I/O thread** 1928 | 1929 | I/O thread는 Slave가 마지막으로 읽었던 이벤트를 기억하고 있다가 Master에게 다음 binary log 로그를 전송해달라고 요청합니다. 그리고 Master의 binlog dump thread가 로그를 보내주면 이것을 Relay log로 저장합니다. 백업을 위해서 I/O thread를 잠시 정지할 수도 있습니다. 하지만, 정지된 상황에서 Master의 binary log가 지워지면 Slave는 Master의 데이터를 복제할 수 없습니다. 1930 | 1931 | - **Relay log** 1932 | 1933 | Relay log는 Slave I/O thread를 통해서 받은 로그를 저장한 것 입니다. 보통 relay log는 SQL thread가 읽고 나면 지웁니다. 따라서 어느 정도 이상의 크기가 되지 않습니다. 하지만 SQL thread가 멈추어 있으면 relay log는 계속해서 크기가 커지게 됩니다. 그렇게 되면 I/O thread는 자동으로 새 relay log 파일을 만들어, 파일이 너무 커지는 것을 막습니다. 1934 | 1935 | - **SQL thread** 1936 | 1937 | SQL thread는 I/O thread가 만든 relay log를 읽어 실행을 시키고, relay log를 지웁니다. 1938 | 1939 | 1940 | 1941 | ## 장점 및 단점 1942 | 1943 | - 장점 1944 | - 데이터 동기화가 비동기 방식이기 때문에 지연시간이 거의 없습니다. 1945 | - DB로 요청하는 Query의 대부분은 읽기 작업입니다. 리플리케이션 구조는 읽기 요청을 Slave에서 전담하여 처리할 수 있으므로 Slave의 Scale을 늘림으로써 부하를 분산시키고 DB의 읽기 속도를 향상 시킬 수 있습니다. 1946 | - Slave에 데이터가 복제되며 Slave는 복제 프로세스를 일시적으로 중지할 수 있기 때문에 특정 시점의 원본 소스 데이터를 손상시키지 않고 백업이 가능합니다. 1947 | - Master에서 현재 데이터를 동기화 한 뒤 Slave에서 서비스에 영향을 주지 않고 데이터의 분석을 실행할 수 있습니다. 1948 | - 여러 지역 혹은 local에 Slave를 복제할 수 있으므로 지리적으로 빠른 응답속도를 보일 수 있으며 문제가 생겼을때 DB의 데이터를 복구하기 수월합니다. 1949 | - 단점 1950 | - 데이터 동기화가 비동기 방식이기 때문에 시간차가 생겨서 Slave에 최신 데이터가 반영되지 않았을 수 있습니다. 1951 | - Master와 Slave의 기능 및 구성의 차이로 인해 Master가 다운되었을 때 클러스터 구조 처럼 Fail over 한 시스템을 만들 수 없습니다. 1952 | 1953 | 1954 | 1955 | ## 리플리케이션 vs 클러스터 1956 | 1957 | - 리플리케이션 1958 | - 여러 개의 DB서버와 DB를 권한에 따라 수직적인 구조(master-Slave)로 구축하는 방식이다. 1959 | - 비동기 방식으로 데이터를 동기화 한다. 1960 | - 데이터 무결성 검사를 하지 않기 때문에 데이터가 동기화로 인한 지연시간이 거의 없다. 1961 | - DB 간에 일관성 있는 데이터를 얻지 못할 수 있다. 1962 | - 클러스터 1963 | - 여러 개의 DB 서버를 수평적인 구조로 구축하는 방식이다. 1964 | - 동기 방식으로 노드들 간의 데이터를 동기화 한다. 1965 | - 데이터를 동기화하는 시간이 필요하므로 리플리케이션에 비해 쓰기 성능이 떨어진다. 1966 | - 1개의 DB 서버가 다운되어도 시스템 장애를 최소화 하도록 Fail Over 하게 운영할 수 있다. 1967 | 1968 | ------- 1969 | 1970 |
1971 | 1972 | 1973 | 1974 | # 데이터베이스 튜닝 1975 | 1976 | ## 데이터베이스 튜닝이란? 1977 | - DB 성능 향상을 위해 필요한 작업을 변경하는 작업 1978 | - 하드웨어의 성능을 향상시키는 것이 아닌 운영체제나 데이터베이스 구조를 이해하고 시스템 모니터링 결과 등을 참고해서 성능 향상을 위해 데이터베이스 설계, 데이터베이스 환경설정, SQL 문장을 변경한다. 1979 | - DB의 성능은 데이터의 저장, 수정을 위해서만이 아닌 **실제 운영에 있어서 매우 중요**하다. 1980 | - 시스템 개발 계획, 시스템 설계, 개발 및 검수, 운영 전 단계에서 데이터베이스 튜닝을 할 수 있다. 1981 | - 설계 단계에서부터 적극적으로 성능에 대해 고려해야 이후 성능에 대한 이슈가 적게 발생한다. 즉, 설계 단계에서 어떻게 하면 효율적인 성능을 가진 시스템을 개발할 수 있을 지에 대한 고민을 하는 것이 매우 중요하다. 1982 | 1983 | ## 데이터베이스 튜닝 목적 1984 | - 주어진 하드웨어 환경에서 처리량과 응답 속도를 개선하기 위함이다. 1985 | - 서비스를 운영하다 보면 새로운 기능을 추가하거나 서비스를 새로 만들 수 있고 이로 인해 운영 환경이나 데이터베이스 테이블 구조 수정, 데이터량의 증가가 발생할 수 있다. 처음엔 서비스를 운영하기에 DB 성능에 문제가 없었지만 지속적인 수정 등으로 인해 성능 저하가 발생할 수 있다. 따라서 이러한 성능 저하를 막고 원활한 운영을 위해서는 DB 튜닝이 필요하다. 1986 | 1987 | ## 데이터베이스 튜닝 방법 1988 | 1. 시스템 현황 분석 1989 | 2. 문제점 탐지 및 원인 분석 1990 | 3. 목표 설정 1991 | 4. 튜닝 실시 1992 | 5. 결과 분석 1993 | 1994 | - 데이터베이스 튜닝을 위해 운영체제나 미들웨어(WAS, DBMS) 등의 영역에서 시스템 모니터링 결과를 참고하는데, 이를 통해 성능이 떨어지는 프로그램 혹은 특정 시점이나 환경에서 성능이 저하되는 상황을 확인한다. 1995 | (미들웨어는 운영체제와 응용 소프트웨어의 중간에서 조정과 중개의 역할을 수행하는 소프트웨어이다(개발과 인프라의 중간 다리 역할). 데이터베이스 시스템, 전자 통신 소프트웨어, 메시지 및 쿼리 처리 소프트웨어가 미들웨어에 속한다.) 1996 | - 문제 상황을 정확히 분석한 후 다양한 해결 방법을 시도한다. 이때, 문제의 해결이 시스템 전체 영역에 영향을 미쳐 시스템 운영에 방해가 될 수 있기 때문에 파급 효과에 대해 고려해야 한다. 1997 | 1998 | 1999 | # 데이터베이스 튜닝 3단계 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2018 | 2019 | 2020 | 2021 | 2022 | 2026 | 2027 | 2028 | 2029 | 2030 | 2034 | 2035 | 2036 |
튜닝 단계튜닝 방안튜닝 사례
DB 설계 튜닝 2010 | DB 설계 단계에서 성능을 고려해서 설계한다. 2011 |
2012 | 2013 | - 데이터베이스 모델링, 인덱스 설계
2014 | - 데이터베이스 용량 산정
2015 | - 데이터 파일, 테이블 스페이스 설계 2016 | (테이블 스페이스: 데이터베이스의 논리적 저장 영역 단위) 2017 |
반정규화/분산파일배치
DBMS 튜닝 2023 | 성능을 고려해서 메모리나 블록의 크기를 지정한다.
2024 | - CPU, 메모리 I/O를 DB 성능을 고려해서 지정
2025 |
Buffer 크기, Cache 크기
SQL 튜닝 2031 | 성능을 고려해서 SQL 작성, 쿼리 문장 수정
2032 | - Join, Indexing, SQL Execution Plan(실행 계획) 2033 |
Hash/Join
2037 | 2038 | ## 데이터베이스 튜닝 영역 별 세부 기법 2039 | 2040 | 2041 | 2042 | 2043 | 2044 | 2045 | 2046 | 2047 | 2048 | 2049 | 2050 | 2051 | 2052 | 2053 | 2054 | 2055 | 2056 | 2057 | 2058 | 2059 | 2060 | 2061 | 2062 | 2063 | 2064 | 2065 | 2066 | 2067 | 2068 | 2069 | 2070 | 2071 | 2072 | 2073 | 2074 | 2075 | 2076 | 2077 | 2078 | 2079 | 2080 | 2081 | 2082 | 2083 | 2084 | 2085 | 2086 | 2087 | 2088 | 2089 | 2090 | 2091 | 2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | 2101 | 2102 | 2103 | 2104 | 2105 | 2106 | 2107 | 2108 | 2109 | 2110 | 2111 | 2112 | 2113 | 2114 | 2115 | 2116 | 2117 | 2118 | 2119 | 2120 | 2121 | 2122 | 2123 | 2124 | 2125 | 2126 | 2127 | 2128 |
튜닝 영역기법기법 설명
DB 설계 튜닝 영역테이블 분할 및 통합파티션 기능, 테이블 수평/수직 분할
식별자 지정/Key 설정본질/인조 식별자 정의, 클러스터링
효율적 인덱스 설정인덱스 분포도 고려 10~15%
정규화/반정규화테이블, 컬럼, 관계 정규화/반정규화
적절한 데이터 타입 선정조인 시 연결되는 데이터 타입 일치
데이터 모델링슈퍼/서브 타입, PK, 파티셔닝, 데이터 통합
DBMS 튜닝 영역I/O 최소화실제 필요한 데이터만 Read, Query off-loading
Buffer Pool 튜닝지역성 관점 데이터 관리, Keep Buffer Cache
Commit/Check PointCheck Point 수해주기 조절, Commit 주기 조정
Thread/ReuseMiddleware 기능과 연동
SQL 튜닝 영역Undo Segment 설정Undo 영역 크기 조정
옵티마이저RBO/CBO 이해, 통계정보 최신화
힌트 사용지원되는 힌트 기반 실행계획 유도
부분범위 처리일부만 Access, 옵티마이저 정보 제공
인덱스 활용인덱스 기반 조회 속도 향상, Sort 연산 대체
조인 방식/순서실행 계획 확인 후 조정
동적 SQL 지양파싱(Parsing) 부하 감소를 위한 Static SQL 사용
다중 처리한 번의 DBMS 호출로 여러 건 동시 처리
병렬 처리하나의 SQL을 여러 개의 CPU가 분할 처리
SORT 튜닝 수행인덱스 기반 MIN, MAX 구하기, TOP-N 쿼리
2129 | 2130 | #### 참고 2131 | 한국데이터산업진흥원, “SQL 전문가 가이드” 2132 | 2133 | 한국데이터산업진흥원, “DAP 전문가 가이드” 2134 | -------------------------------------------------------------------------------- /Database/img/cartesian-join-row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/cartesian-join-row.png -------------------------------------------------------------------------------- /Database/img/cartesian-join-where.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/cartesian-join-where.png -------------------------------------------------------------------------------- /Database/img/cartesian-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/cartesian-join.png -------------------------------------------------------------------------------- /Database/img/cartesian-right-join-row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/cartesian-right-join-row.png -------------------------------------------------------------------------------- /Database/img/cartesian-right-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/cartesian-right-join.png -------------------------------------------------------------------------------- /Database/img/cartesian-where-row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/cartesian-where-row.png -------------------------------------------------------------------------------- /Database/img/clustering_active_active.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/clustering_active_active.PNG -------------------------------------------------------------------------------- /Database/img/clustering_active_standby.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/clustering_active_standby.PNG -------------------------------------------------------------------------------- /Database/img/clustering_load_balance.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/clustering_load_balance.PNG -------------------------------------------------------------------------------- /Database/img/clustering_primay_secondary.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/clustering_primay_secondary.PNG -------------------------------------------------------------------------------- /Database/img/db-sql-joins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/db-sql-joins.jpg -------------------------------------------------------------------------------- /Database/img/outer-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/outer-join.png -------------------------------------------------------------------------------- /Database/img/outer-on-and.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/outer-on-and.png -------------------------------------------------------------------------------- /Database/img/outer-on-where.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/outer-on-where.png -------------------------------------------------------------------------------- /Database/img/replication_master_slave.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/replication_master_slave.PNG -------------------------------------------------------------------------------- /Database/img/replication_master_slave2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/replication_master_slave2.PNG -------------------------------------------------------------------------------- /Database/img/replication_master_slave3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/replication_master_slave3.PNG -------------------------------------------------------------------------------- /Database/img/self-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Database/img/self-join.png -------------------------------------------------------------------------------- /DesignPattern/img/AbFactory1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/AbFactory1.png -------------------------------------------------------------------------------- /DesignPattern/img/AbFactory2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/AbFactory2.png -------------------------------------------------------------------------------- /DesignPattern/img/AbFactory3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/AbFactory3.png -------------------------------------------------------------------------------- /DesignPattern/img/Deco1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Deco1.png -------------------------------------------------------------------------------- /DesignPattern/img/Deco2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Deco2.png -------------------------------------------------------------------------------- /DesignPattern/img/Deco3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Deco3.png -------------------------------------------------------------------------------- /DesignPattern/img/Deco4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Deco4.png -------------------------------------------------------------------------------- /DesignPattern/img/Deco5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Deco5.png -------------------------------------------------------------------------------- /DesignPattern/img/Strategy_class.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Strategy_class.PNG -------------------------------------------------------------------------------- /DesignPattern/img/Strategy_robot.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Strategy_robot.PNG -------------------------------------------------------------------------------- /DesignPattern/img/Strategy_strategy.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/Strategy_strategy.PNG -------------------------------------------------------------------------------- /DesignPattern/img/adapter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/adapter.jpg -------------------------------------------------------------------------------- /DesignPattern/img/adapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/adapter.png -------------------------------------------------------------------------------- /DesignPattern/img/command_class_diagram.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/command_class_diagram.PNG -------------------------------------------------------------------------------- /DesignPattern/img/command_example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/command_example1.png -------------------------------------------------------------------------------- /DesignPattern/img/command_example2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/command_example2.PNG -------------------------------------------------------------------------------- /DesignPattern/img/factory1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/factory1.gif -------------------------------------------------------------------------------- /DesignPattern/img/factory2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/factory2.png -------------------------------------------------------------------------------- /DesignPattern/img/factory3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/factory3.png -------------------------------------------------------------------------------- /DesignPattern/img/factory4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/factory4.png -------------------------------------------------------------------------------- /DesignPattern/img/state_class_diagram.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/DesignPattern/img/state_class_diagram.PNG -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Gooder 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 | -------------------------------------------------------------------------------- /Network/img/Asyn-block.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/Asyn-block.gif -------------------------------------------------------------------------------- /Network/img/Asyn-nonblock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/Asyn-nonblock.gif -------------------------------------------------------------------------------- /Network/img/IPv4_Datagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/IPv4_Datagram.png -------------------------------------------------------------------------------- /Network/img/IPv6_Datagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/IPv6_Datagram.png -------------------------------------------------------------------------------- /Network/img/IPv6_Datagram_Payload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/IPv6_Datagram_Payload.png -------------------------------------------------------------------------------- /Network/img/Syn-block.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/Syn-block.gif -------------------------------------------------------------------------------- /Network/img/Syn-nonblock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/Network/img/Syn-nonblock.gif -------------------------------------------------------------------------------- /OS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/.DS_Store -------------------------------------------------------------------------------- /OS/README.md: -------------------------------------------------------------------------------- 1 | # Operating System(OS) 운영체제 2 | 3 | 1. [운영체제란?](#운영체제란) 4 | 2. [프로세스와 쓰레드](#프로세스와-쓰레드-process-and-thread) 5 | 3. [인터럽트](#인터럽트-interrupt) 6 | 4. [시스템 콜](#시스템-콜) 7 | 5. [PCB와 Context Switching](#PCB와-Context-Switching) 8 | 6. [IPC](#IPC(Inter-Process-Communication)) 9 | 7. [CPU 스케줄링](#CPU-스케줄링-(CPU-Scheduling)) 10 | 8. [Deadlock 교착상태](#Deadlock-교착상태) 11 | 9. [Race Condition](#Race-Condition) 12 | 10. [세마포어 & 뮤텍스](#세마포어와-뮤텍스) 13 | 11. [메모리 & 가상 메모리](#주-메모리와-가상-메모리) 14 | 12. [파일 시스템](#파일시스템file-system) 15 | 16 |
17 | 18 | # 운영체제란? 19 | 20 | 운영체제(Operating System)는 컴퓨터 **시스템 자원들을 효율적으로 관리**하여 사용자의 편의성과 시스템 성능을 극대화하는 시스템 소프트웨어 입니다. 21 | 22 | 컴퓨터 사용자와 컴퓨터 하드웨어 간의 **인터페이스로 동작**합니다. 23 | 24 | 응용프로그램은 운영체제가 제공하는 자원만을 사용할 수 있습니다. 25 | 26 | 27 |

28 | 29 | 30 | ## 부팅(Booting) 31 | 32 | 운영체제는 다음의 순서로 실행됩니다. 33 | 34 |

35 | 36 | 1. 컴퓨터의 전원이 켜진다. 37 | 2. 프로세서(CPU)에서 ROM에 있는 내용을 읽는다. 38 | - ROM 안에는 POST(Power-On Self-Test), 부트 로더(boot loader)가 저장되어 있다. 39 | 3. POST는 현재 컴퓨터의 상태를 검사한다. 40 | 4. 부트 로더가 실행되어 하드디스크에 저장되어 있는 운영체제를 찾아서 RAM에 가지고 온다. 41 | 42 | 43 | 44 | ## Shell 과 Kernel 45 | 46 | 운영체제는 크게 셸과 커널로 나누어집니다. 47 | 48 |

49 | 50 | 셸(Shell)은 명령어 해석기입니다. 사용자의 지시를 해석하여 시스템에 전달하는 인터페이스 역할을 합니다. sh, bash 등이 있습니다. 51 | 52 | 53 | 54 | 커널(Kernel)은 운영체제의 핵심 기능을 하는 제어 프로그램입니다. 프로그램이 요청한 처리를 하드웨어에 나누어 처리를 요구합니다. 시스템 콜을 수행하며, 메모리 관리, 프로세스 관리, 파일 시스템 관리, 입출력 관리, 프로세스 간 통신 관리 등의 작업을 수행합니다. 55 | 56 | - 프로세스 관리 : 프로세스에 CPU를 분배하고 작업에 필요한 제반 환경 제공 57 | - 메모리 관리 : 프로세스에 작업 공간을 배치하고 실제 메모리보다 큰 가상공간 제공 58 | - 파일 시스템 관리 : 데이터 저장하고 접근 할 수 있는 인터페이스 제공 59 | - 입출력 관리 : 필요한 입출력 서비스 제공 60 | - 프로세스 간 통신 관리 : 공동 작업을 위한 각 프로세스 간 통신 환경 제공 61 | 62 |
63 | 64 | # 프로세스와 쓰레드 (Process and Thread) 65 | 66 | ## 프로세스 67 | 68 | 프로세스(Process)는 운영체제로부터 자원을 할당 받은 작업의 단위입니다. 69 | 70 | 프로그램을 실행하면 운영체제는 프로그램 파일을 컴퓨터 메모리 공간에 할당합니다. 71 | 72 | 즉, 메모리 공간을 할당받아 실행되고 있는 프로그램을 프로세스라고 할 수 있습니다. 73 | 74 | 운영체제는 프로세스마다 각각 독립된 메모리 영역을 Code/Data/Stack/Heap 형식으로 할당해줍니다. 75 | 76 | Data에는 전역 변수들이 저장되고 Stack에는 함수의 매개변수, return 주소, 로컬 변수와 같은 임시 값들을 저장합니다. heap에는 프로세스 실행 중에 동적으로 할당되는 값들이 저장됩니다. 77 | 78 |

79 | 80 | 각 프로세스는 별도의 메모리 공간에서 실행되기 때문에 다른 프로세스의 자원에 접근할 수 없으며, 81 | 82 | 접근하려면 IPC(Inter Process Communication)를 사용해야 합니다. 83 | 84 | 85 | 86 | ## 쓰레드 87 | 88 | 쓰레드(Thread)는 프로세스가 할당 받은 자원을 이용하는 실행 흐름의 단위입니다. 89 | 90 | 쓰레드는 프로세스의 작업들을 실행 흐름에 따라 분리한 것입니다. 91 | 92 | 기본 적으로 프로세스는 최소 1개의 쓰레드를 가지고 있다. 이를 메인 쓰레드라고 합니다. 93 | 94 | 쓰레드는 프로세스 안에 존재합니다. 프로세스와 쓰레드를 코드에 비유하면 프로세스는 코드 전체이고 쓰레드는 그 중 main 함수와 같이 함수들이 될 수 있습니다. 95 | 96 | 쓰레드는 프로세스 내에서 Stack만 따로 할당받고, Code, Data, Heap 영역은 공유합니다. 97 | 98 |

99 | 100 | 그래서 프로세스와 다르게 쓰레드 간의 일부 공간이나 자원을 공유하여 작동합니다. 101 | 102 |

103 | 104 | 105 | 106 | ## 멀티 쓰레드 107 | 108 | 하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상시키는 것을 멀티스레딩이라고 합니다. 이 경우 각각의 쓰레드는 독립적인 작업을 수행해야 하기 때문에 각자의 스택과 PC 레지스터 값을 갖고 있습니다. 109 | 110 | 111 | #### 스택을 쓰레드마다 독립적으로 할당하는 이유 112 | 113 | 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수 등을 저장하기 위해 사용되는 메모리 공간입니다. 114 | 115 | 독립적인 실행 흐름을 추가하기 위해서는 독립적인 함수 호출이 가능해야 합니다. 그래서 스택 메모리 공간이 독립적으로 존재해야 합니다. 116 | 117 | 따라서 쓰레드의 정의에 따라 독립적인 실행 흐름을 추가하기 위한 최소 조건으로 독립된 스택을 할당합니다. 118 | 119 | 120 | #### PC Register 를 쓰레드마다 독립적으로 할당하는 이유 121 | 122 | 쓰레드는 CPU 를 할당받았다가 스케줄러에 의해 다시 반환합니다. 그래서 PC Register에 쓰레드가 명령어의 어느 부분까지 수행했는지 PC 값을 저장해놓을 필요가 있습니다. 123 | 124 | 따라서 PC 레지스터를 독립적으로 할당합니다. 125 | 126 | 127 | ## 멀티 프로세스 VS 멀티 쓰레드 128 | 129 | 멀티 프로세스는 하나의 응용 프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 수행하도록 하는 것입니다. 130 | 131 | - 장점 132 | - 멀티 프로세스는 프로세스 중 하나에 문제가 발생했을 때 그 프로세스 외의 프로세스에 영향이 생기지 않습니다. 133 | - 단점 134 | - Context Switching이 발생하면 CPU 레지스터와 캐쉬에 있는 데이터를 모두 리셋해야 하므로 오버헤드가 매우 큽니다. 135 | - 프로세스는 각각의 독립된 메모리 영역을 할당 받았기 때문에 프로세스 사이의 통신을 위해서는 IPC를 이용해야 합니다. 136 | 137 | 멀티 쓰레드는 하나의 응용 프로그램을 여러 개의 쓰레드로 구성하여 각 쓰레드가 하나의 작업을 수행하도록 하는 것입니다. 대표적으로 웹 서버가 멀티 쓰레드 응용 프로그램입니다. 많은 운영체제들이 멀티 프로세스를 지원하지만 멀티 쓰레드를 기본으로 합니다. 138 | 139 | - 장점 140 | - 쓰레드 간 데이터 공유가 가능하므로 데이터를 주고 받는 것이 비교적 수월합니다. 141 | - Context Switching이 발생했을 때 stack 영역만 처리하므로 더 적은 오버헤드가 발생합니다. 142 | - 더 적은 메모리 영역이 필요하므로 시스템의 자원 소모도 감소할 수 있습니다. 143 | - 단점 144 | - 쓰레드 중 하나에 문제가 발생했을 때 전체 프로세스에 영향을 끼치는 단점이 있습니다. 145 | - 자원을 공유하기 때문에 **동기화 문제가 발생**할 수 있습니다. 146 | 147 | 정리하면 멀티 쓰레드는 멀티 프로세스에 비해 자원의 효율성 증대, 처리 비용 감소, 응답 시간 단축의 이점이 있지만 쓰레드에 문제가 생겼을 때 전체 프로세스에 영향이 생긴다는 것과 동기화 문제가 발생할 수 있으므로 이를 적절히 해결해 주어야 한다는 주의점이 있습니다. 148 | 149 |
150 | 151 | 152 | 153 | # 인터럽트 (Interrupt) 154 | 155 | 인터럽트란 프로세서가 프로그램을 실행하고 있을 때, 입출력 장치나 예외상황의 핸들링이 필요할 경우 프로세서에서 실행 중인 프로그램을 멈추고 상황을 처리하도록 하는 명령입니다. 156 | 157 | 주요 인터럽트로는 CPU 선점형 스케쥴러의 타이머 인터럽트, 입출력 인터럽트, 1/0 연산 인터럽트(Divide-by-Zero Interrupt)과 등이 있습니다. 158 | 159 | 160 | 161 | ## 인터럽트 종류 162 | 163 | - 하드웨어 인터럽트(=외부 인터럽트) 164 | 165 | - 입출력장치, 타이밍 장치, 전원 등 외부적인 요인에 의해 발생합니다. 166 | - ISR 종료 후 대기합니다. 167 | 168 | - 소프트웨어 인터럽트(=내부 인터럽트) 169 | 170 | - 소프트웨어가 OS 서비스를 요청하거나 에러를 일으켰을 때 발생합니다. 171 | 172 | - 파일 읽기/쓰기, 0으로 나누기, Overflow 등이 있습니다. 173 | 174 | - ISR 종료 후 다시 프로그램으로 돌아거나 프로그램을 강제로 종료합니다. 175 | 176 | - **시스템 콜**도 의도적으로 일으킨 예외 인터럽트입니다. 177 | 178 | 179 | 180 | ## 인터럽트 처리 과정 181 | 182 | 프로그램 실행 중 인터럽트가 발생하였다면, 183 | 184 |

185 | 186 | - CPU는 실행 중이던 명령어를 마치고 인터럽트 라인을 통해 인터럽트가 걸렸음을 인지합니다. 187 | 188 | - **인터럽트 벡터**를 읽고 ISR 주소값을 얻어 **ISR(Interrupt Service Routine)**로 점프하여 루틴을 실행합니다. 189 | 190 | - 인터럽트 벡터는 인터럽트 발생시 처리해야 할 ISR의 주소를 인터럽트 별로 보관하고 있는 테이블입니다. 191 | 192 | - ISR은 인터럽트 핸들러라고도 하며 인터럽트를 처리하는 프로그램이며 OS에서 지원합니다. 인터럽트별로 처리해야할 내용이 있습니다. 193 | 194 | - ISR에서 동기화를 막기 위해 인터럽트를 금지합니다. 195 | 196 | - 프로세서는 현재까지 수행중이었던 상태를 해당 process의 **PCB(Process Control Block)**에 저장합니다. 197 | 198 | - PC(Program Counter, IP)에 다음에 실행할 명령의 주소를 저장합니다. 199 | 200 | - 해당 인터럽트를 처리합니다. 201 | 202 | - 다 처리하면, 대피시킨 프로세서의 상태를 복원합니다. 203 | 204 | - ISR의 끝에 IRET 명령어에 의해 인터럽트가 해제됩니다. 205 | 206 | - IRET 명령어가 실행되면, 대피시킨 PC 값을 복원하여 이전 실행 위치로 복원합니다. 207 | 208 | 209 | 210 | ## 인터럽트가 없다면? 211 | 212 | 입출력 연산은 프로세서의 명령 수행 연산보다 훨씬 느립니다. 213 | 214 | 예를 들어 프로세서가 입력 장치를 주기적으로 검사하며 신호를 기다린다면(Polling 방식) 그 때 마다 프로세서는 다른 작업을 수행할 수 없기 때문에 프로세서의 오버헤드가 증가하여 시간이 낭비될 것입니다. 215 | 216 | 하지만, 인터럽트가 입출력 장치의 처리 신호를 보내준다면 프로세서가 다른 작업을 하고 있다가 그 작업을 처리할 수 있게 됩니다. 217 | 218 |
219 | 220 |
221 | 222 | # 시스템 콜 223 | 224 |
225 | 226 | ## 1. CPU 모드 227 | 228 | CPU는 사용자 애플리케이션(User Application)이 시스템을 손상시키는 것을 방지하기 위해 2가지 모드를 제공한다. CPU에 있는 Mode bit로 모드를 구분하며 0은 커널 모드(운영체제 프로세스 실행) 1은 사용자 모드(사용자 프로세스 실행)를 나타낸다. 229 | 230 | - 사용자 모드(User Mode) 231 | 232 | 사용자 모드에서 사용자 애플리케이션 코드가 실행된다. 사용자가 접근할 수 있는 영역에 제한이 있기 때문에 해당 모드에서는 하드웨어(디스크, I/O 등) 에 직접적으로 접근할 수 없다. 접근을 위해서는 시스템콜(System Call)을 사용해야한다. 사용자 애플리케이션의 각 스레드들은 고유의 사용자 모드 스택을 가진다. 233 | 234 | 235 | 236 | - 커널 모드(Kernel Mode) 237 | 238 | 운영체제(OS)가 CPU를 사용하는 모드이다. 시스템콜을 통해 커널모드로 전환이 되면 운영체제는 하드웨어를 제어하는 명령어(Privileged Instructions)를 실행한다. Privileged Instructions은 사용자 모드에서 실행되면 exception이 발생한다. 239 | 240 |

241 |

242 |
243 | 244 |
245 | 246 | ## 2. 시스템콜(System Call) 247 | 248 | 운영체제에서 제공하는 서비스들을 사용하기 위한 프로그래밍 인터페이스이다. 보통 직접적으로 시스템 콜을 사용하기보다 API(라이브러리 함수)를 통해 사용하게 된다. 249 | 250 | 251 |

252 |

253 | 254 |
255 | 256 | 257 | 258 | ### 시스템 콜 종류 259 | 260 | 시스템 콜은 프로세스 제어, 파일 조작, 디바이스 조작, 정보 유지, 통신, 보호 크게 6가지로 분류할 수 있다. 261 | 262 |
263 | 264 | 1. 프로세스 제어(Process Control) 265 | - 프로세스 생성/제거 266 | - 끝내기, 중지 267 | - 적재, 실행 268 | - 대기 269 | - 메모리 할당/해제 270 | 271 | 2. 파일 조작(File Manipulation) 272 | - 파일 생성/삭제 273 | - 열기/닫기/읽기/쓰기 274 | 275 | 3. 디바이스 조작(Device Manipulation) 276 | - 장치 요청/해제 277 | - 장치 읽기/쓰기/위치 변경 278 | - 속성 설정 279 | 280 | 4. 정보 유지(Information Maintenance) 281 | - 시간, 날짜 설정/요청 282 | 283 | 5. 통신(Communication) 284 | - 통신 연결 생성/제거 285 | - 송신/수신 286 | 287 | 6. 보호(Protection) 288 | - 권한 관리 289 | 290 | 291 | 292 |

293 |

294 |
295 | 296 | ### 시스템 콜 vs 라이브러리 함수 297 | 298 | #### **시스템 콜** 299 | 300 | 커널 자원을 사용자가 사용할 수 있도록 만들어 놓은 함수들이며 호출 시 커널 모드로 전환이 되어 실행된다. 리턴 타입은 대부분 int이고 오류는 -1, 정상은 0 이상의 값을 반환한다. 301 | 302 |
303 | 304 | #### **라이브러리 함수** 305 | 306 | 문자열/표준 입출력 등 사용자가 많이 사용하는 기능들을 미리 함수로 만들어 놓은 것이며 내부적으로 시스템 콜을 사용하지만 호출 시 사용자 모드에서 실행된다. 목적에 따라 다양한 타입의 리턴값을 갖으며 개발을 쉽게 만들거나 시스템 콜 호출을 최소화하기 위해 제공된다. 예를 들어, 파일 입/출력시 read(), write()와 같은 시스템 콜들을 호출할 때마다 커널 모드로 전환되어 바로 파일에 기록된다. 반면 라이브러리 함수인 fread(), fwrite()의 경우는 버퍼를 사용해 내부적으로 한번만 read(), write()를 실행하기 때문에 시스템 자원을 효율적으로 사용하게 된다. 내부적으로 시스템 콜을 호출하기 때문에 wrapper 함수라고도 부른다. 307 | 308 | Windows API, POSIX API, Java API 등이 있다. 309 |

310 |

311 | 312 | 313 |
314 | 315 | ### 시스템 콜 실행 과정(Linux) 316 | 317 |

318 |

319 | 320 | ``` 321 | 1. 라이브러리 함수(printf)를 호출한다. 322 | 2. 라이브러리 함수 내부에서 시스템 콜(write)를 호출한다. 323 | 3. 해당 시스템 콜의 인덱스(4)를 CPU 레지스터에 저장한다. 324 | 4. 0x80 인터럽트를 발생시킨다.(커널 모드로 전환) 325 | 5. IDT(Interrupt Descriptor Table)를 참조하여 system_call()을 호출한다. 326 | 6. 이때 3에서 저장한 인덱스를 system_call() 함수 내에 전달한다. 327 | 7. sys_call_table을 참조해 해당 인덱스에 맞는 기능(sys_write)을 호출한다. 328 | 8. 수행이 모두 끝나면 사용자 모드로 전환된다. 329 | ``` 330 |
331 | 332 |
333 | 334 | # PCB와 Context Switching 335 | 336 | ## PCB(Process Controll Block) 337 | 338 | PCB는 OS에서 **프로세스에 대한 중요 정보를 저장**하고 있는 자료구조입니다. OS는 프로세스를 관리하기 위해 **프로세스의 생성과 동시에 고유한 PCB 를 생성**합니다. 339 | 340 |

341 | 342 | > 프로그램 실행 -> 프로세스 생성 -> 프로세스 주소 공간에 (stack, data, stack) 생성 -> 이 프로세스의 메타데이터들이 PCB에 저장 343 | 344 | CPU에서 프로세스 수행 중에 작업을 멈추고 다른 프로세스를 처리해야 하는 경우가 생깁니다. 그 때, 기존에 수행하고 있던 프로세스에 프로세스의 정보를 저장하는 곳이 PCB입니다. 345 | 346 | OS는 PCB에 현재까지 수행한 프로세스의 상태를 저장하고 CPU를 반납합니다. 그래서 PCB에는 이전까지 수행하고 있던 **프로세스가 다음에 수행해야 할 상태값**이 저장됩니다. 347 | 348 | **프로세스가 종료되면 OS는 해당 프로세스의 PCB를 제거**합니다. 349 | 350 | 351 | 352 | ## PCB에 저장되는 정보 353 | 354 |

355 | 356 | - 프로세스 식별자(Process ID, PID) : 프로세스 식별번호 357 | - 프로세스 상태 : new, ready, running, waiting, terminated 등의 상태를 저장 358 | - 프로그램 카운터 : 프로세스가 다음에 실행할 명령어의 주소 359 | - CPU Register 정보 360 | - CPU 스케쥴링 정보 : 프로세스의 우선순위, 스케줄 큐에 대한 포인터 등 361 | - 메모리 관리 정보 : 페이지 테이블 또는 세그먼트 테이블 등과 같은 정보를 포함 362 | - Accounting 정보 : 사용된 CPU 시간, 시간제한, 계정번호 등 363 | - 입출력 상태 정보 : 프로세스에 할당된 입출력 장치들과 열린 파일 목록 364 | 365 | 366 | 367 | ## Context Switching 368 | 369 | Context Switching은 **CPU가 현재 수행하고 있는 작업(Process, Thread)의 상태를 저장하고 다음 진행할 작업의 상태 및 Register 값들에 대한 정보(Context)를 읽어 새로운 작업의 Context 정보로 교체하는 과정**을 말합니다. 여기서 Context란 CPU가 다루는 작업에 대한 정보를 말하고, 대부분의 정보는 Register에 저장되고 PCB로 관리됩니다. 그래서 이를 위의 **PCB의 역할에 맞추어 말하면 CPU가 이전의 프로세스 상태를 PCB에 보관하고, 또 다른 프로세스의 정보를 PCB에서 읽어서 레지스터에 적재하는 과정**을 말합니다. 370 | 371 | Context Switching은 Interrupt가 발생하거나, 실행 중인 CPU 사용 시간을 모두 소모하거나, 입출력을 위해 대기해야 하는 경우 발생합니다. 372 | 373 | 즉, Context Switching은 **프로세스가** Ready -> Running , Running -> Ready , Running -> Block 처럼 **상태 변경 시에 발생**합니다. 그러므로 **Context Switching을 하는 주체는 CPU 스케쥴러**입니다. 374 | 375 | 376 | 377 | ## Context Switching 수행 과정 378 | 379 |

380 | 381 | > 프로세스 P0과 P1이 존재하고 P0이 CPU를 점유 중이고, P1이 대기 중일 때 Interrupt나 System Call이 발생하여 P1이 CPU를 점유하게 된다면 위와 같은 Context Switching 과정이 수행 됩니다. 382 | 383 | 384 | 385 | ## Context Switching Overhead 386 | 387 | Context Switching이 발생하게 되면 다음과 같은 과정이 필요합니다. 388 | 389 | - Cache 초기화 390 | 391 | - Memory Mapping 초기화 392 | 393 | - 메모리의 접근을 위해서 Kernel은 항상 실행되어야 합니다. 394 | 395 | 이 과정에서 소요되는 시간을 Cost라고 표현합니다. **Cost는 낭비되는 시간**이라고 생각할 수 있습니다. 이렇게 어떤 과정을 할 때 소모되는 Cost들을 Overhead라고 합니다. 그러므로 **어떤 작업을 할 때 Overhead가 높다는 것은 그 과정을 수행하기 위해 필요한 다른 작업들의 Cost가 높다**고 할 수 있습니다. 396 | 397 | 따라서 Context Switching은 Overhead가 높은 작업이고 잦은 Context Switching 는 성능 저하를 가져옵니다. 398 | 399 | Context Switching이 높은 Overhead를 갖음에도 수행하는 이유는 그것을 감안해도 더 이득이기 때문입니다. 예를들어 **프로세스를 수행하다가 I/O event가 발생하여 BLOCK 상태로 전환시켰을 때, CPU가 그냥 놀게 놔두는 것보다 다른 프로세스를 수행시키는 것이 효율적**이므로, Context Switching을 수행하여 CPU로 다른 프로세스를 실행시킵니다. 400 | 401 | 402 | 403 | > **Context Switching과 Interrupt** 404 | 405 | CPU는 하나의 프로세스 정보만을 기억합니다. 여러 개의 프로세스가 실행되는 다중 프로그래밍 환경에서 CPU는 각각의 프로세스의 정보를 저장했다 복귀하고 다시 저장했다 복귀하는 일을 반복합니다. 프로세스의 저장과 복귀는 프로세스의 중단과 실행을 의미합니다. 프로세스의 중단과 실행 시 Interrupt가 발생하므로, Context Switching이 많이 일어난다는 것은 Interrupt가 많이 발생한다는 것을 의미합니다. 406 | 407 | 408 | 409 | > **Context Switching과 시간 할당량** 410 | 411 | 프로세스들의 시간 할당량은 시스템 성능의 중요한 역할을 합니다. 시간 할당량이 적을수록 사용자 입장에서는 여러 개의 프로세스가 거의 동시에 수행되는 느낌을 갖지만 Interrupt의 수와 Context Switching의 수가 늘어납니다. 412 | 413 | ------ 414 | 415 | 416 | 417 |
418 | 419 | # IPC(Inter-Process Communication) 420 | 421 | IPC는 **프로세스들 간에 데이터를 주고 받는 통신 또는 그 방법**입니다. 422 | 423 | 프로세스는 각각 OS로부터 할당받은 독립된 메모리 공간에서 실행됩니다. 하지만 정보 공유, 분산 처리로 작업 속도 향상, 시스템 기능 모듈화 등을 위해서 데이터를 공유하거나 서로 통신이 필요할 때가 있습니다. 이때 사용할 수 있도록 커널에서 여러 방식의 IPC를 제공합니다. 424 | 425 | 426 | 427 |

428 | 429 | 430 | 431 | IPC 는 크게 **Message Passing(메시지 전달) 방식**과 **Shared Memory(공유 메모리) 방식**이 있습니다. 432 | 433 | 434 | 435 | ## Message Passing(메시지 전달 방식) 436 | 437 | Message Passing은 memory protection을 위해 OS가 커널 내부에 메시지를 기록할 수 있는 공간을 마련해 두어서 receive와 send 시스템 콜을 이용하여 메시지를 커널이 대리 전달합니다. 따라서 OS의 간섭이 지속적으로 필요합니다. 같은 곳을 읽고 쓰는 것이 아니므로 동기화 문제가 발생하지 않으나 커널을 거쳐야 하기 때문에 시간이 오래 걸려 성능이 좋지 않습니다. 또한 시스템 콜을 매번 사용하므로 오버헤드 발생할 수 있습니다. 438 | 439 | 440 | 441 | ### PIPE (익명 PIPE) 442 | 443 |

444 | 445 | 파이프는 두 개의 프로세스를 연결하는 1:1 통신입니니다. 이때, 하나의 프로세스는 데이터를 쓰기만, 다른 하나는 데이터를 읽기만 하는 **단방향 통신**만 가능합니다. 한쪽 방향으로만 통신이 가능한 파이프의 특징 때문에 Half-Duplex(반이중) 통신이라고 부르기도 합니다. 446 | 447 | PIPE와 같은 반이중 통신의 경우 하나의 통신선로는 읽기나 쓰기 중 하나만 가능하므로 만약 읽기와 쓰기, 즉 송/수신을 모두 하기 원한다면 두개의 파이프를 만들어야 합니다. 448 | 449 | read()와 write()가 기본적으로 block mode로 작동되기에 프로세스가 read 대기 중이라면 read가 끝나기 전에 write를 할 수 없습니다. 450 | 451 | - 장점 452 | - 매우 간단하게 사용할 수 있습니다. 453 | - 한쪽 프로세스가 단지 읽기만 하고 다른 쪽 프로세스는 단지 쓰기만 하는, 단순한 데이터 흐름에 적합합니다. 454 | - 단점 455 | - 반이중 통신이므로 프로세스가 읽기와 쓰기 통신 모두를 해야 한다면 PIPE를 두개 만들어야 합니다. 456 | - **부모-자식 프로세스** 간에만 사용 가능합니다. 457 | 458 | > 부모-자식 프로세스 459 | > 460 | > 프로세스는 실행되는 도중 시스템 콜을 통해 새로운 프로세스를 생성할 수 있습니다. 461 | > 462 | > 다른 프로세스를 생성한 프로세스를 부모 프로세스, 생성 된 프로세스를 자식 프로세스라고 합니다. 463 | 464 | 465 | 466 | ### Named PIPE(FIFO) 467 | 468 | 익명 파이프(Pipe)는 부모-자식 프로세스와 같이 통신을 할 프로세스를 명확하게 알 수 있는 경우 사용합니다. 이에 반해, Named PIPE는 프로세스 통신을 위해 **이름이 있는 파일을 사용**하기 때문에 전혀 모르는 상태의 프로세스들 사이의 통신에서도 사용합니다. 469 | 470 | Named PIPE의 생성은 mkfifo를 통해 이뤄지는데, mkfifo가 성공하면 명명된 파일이 생성됩니다. 471 | 472 | PIPE 방식은 모두 먼저 입력된 데이터가 먼저 전달되는 흐름을 가진다는 측면에서 동일한 데이터 흐름 메커니즘을 가집니다. 473 | 474 | - 장점 475 | - 익명 pipe와 비슷합니다. 476 | - 익명 pipe와 다르게 부모-자식간의 프로세스가 아니어도 통신이 가능합니다. 477 | 478 | - 단점 479 | 480 | - 익명 pipe와 비슷합니다. 481 | 482 | 483 | 484 | ### Message Queue 485 | 486 |

487 | 488 | Message Queue는 고정된 크기를 갖는 메시지의 연결 리스트를 이용한 메시지 단위의 통신입니다. 메세지의 형태는 사용자가 정의할 수 있으며, 통신하고자 하는 프로세스 간에 정의가 필요합니다. 입출력 방식으로 보자면 위의 Named PIPE와 동일하다고 볼 수 있지만, Name PIPE가 데이터의 흐름이라면 Message Queue는 **메모리 공간**이라는 차이가 있습니다. 489 | 490 | Message Queue 는 어디에서나 물건을 꺼낼 수 있는 컨테이너 벨트라고 볼 수 있습니다. Message Queue에 쓸 데이터에 번호를 붙임으로써 여러 개의 프로세스가 동시에 데이터를 쉽게 다룰 수 있습니다. 491 | 492 | - 장점 493 | - 비동기 방식입니다. 큐에 넣은 데이터를 나중에 처리할 수 있습니다. 494 | - 분산 처리 및 경쟁 처리에 사용할 수 있습니다. 495 | - 단점 496 | - 메시지가 잘 전달되었는지 알 수 없습니다. 497 | - 큐에 데이터를 넣고 빼는 과정에서 Overhead가 발생합니다. 498 | - 데이터가 많이 쌓이면 추가적인 메모리 자원이 필요합니다. 499 | 500 | 501 | 502 | ### Socket 503 | 504 |

505 | 506 | 507 | 508 | Socket은 일반적으로 두 네트워크 프로그램 사이에서 데이터의 입출력의 관문, 또는 그를 위한 운영체제의 API로 많이 쓰입니다. 파이프 관점을 네트워크로 확장한 것으로 생각할 수 있습니다. 그래서 프로세스들 사이의 통신에서도 OS가 제공하는 Port를 통해 사용할 수 있습니다. 509 | 510 | - 장점 511 | - 양방향 통신이 가능합니다. 512 | - 패킷 단위로 주고 받습니다. 513 | - 서버/클라이언트 환경을 구축할 수 있습니다. 514 | 515 | 516 | 517 | ## Shared Memory(공유 메모리 방식) 518 | 519 | 다수의 프로세스가 동시에 작동하는 Linux 운영체제의 특성상 프로세스의 메모리 영역은 반드시 보호되어져야 합니다. 그렇지만 메모리 영역에 있는 데이터를 다른 프로세스도 사용할 수 있도록 해야하는 경우도 있습니다. Thread에서 처럼 메모리 영역을 공유한다면 더 편하게 데이터를 함께 사용할 수 있을 것입니다. 520 | 521 | Shared Memory(공유 메모리)는 **프로세스간 메모리 영역을 공유해서 사용할 수 있도록** **허용**합니다. 프로세스가 공유 메모리 할당을 커널에 요청하면 커널은 해당 프로세스에 메모리 공간을 할당해줍니다. 이후 접근할 프로세스들이 규약을 정해서 해당 메모리 영역에 접근할 수 있습니다. 522 | 523 | 공유메모리는 커널이 처음 생성하지만 이후에 커널의 도움 없이 곧바로 메모리에 접근할 수 있기 때문에 다른 모든 IPC들 중에서 가장 빠르게 작동할 수 있습니다. 하지만, Producer-Consumer Problem 같은 동기화 문제가 생길 수 있기 때문에 Semaphore 등으로 해결해야 합니다. 524 | 525 | - 장점 526 | 527 | - 커널의 관여 없이 메모리를 직접 사용하여 IPC들 중에서 속도가 가장 빠릅니다. 528 | - Message Passing에 비해 한 번에 대량의 데이터 통신이 가능합니다. 529 | 530 | - 단점 531 | 532 | - 커널의 관여가 없기 때문에 동기화 문제를 직접 처리해야 하므로 구현이 어렵습니다. 533 | 534 | - Producer-Consumer Problem 535 | 536 | 537 | 538 | > ##### **Producer-Consumer Problem** 539 | > 540 | > 정보를 생산하는 Producer와 정보를 소비하는 Consumer 프로세스가 있다. 이 두 프로세스는 같은 공간을 공유한다. 두 프로세스가 생산과 소비를 반복하면서 문제가 발생할 수 있다. 541 | > 542 | > 1. 생산자가 생산하려고 할 때 더 이상 저장할 공간이 없는 문제가 발생할 수 있고, 543 | > 2. 이 공간에 소비자가 더 이상 소비할 아이템이 없는 경우가 발생할 수 있다. 544 | 545 | 546 | 547 | ### Memory Map 548 | 549 | Memory Map은 열린 파일을 메모리에 맵핑시켜서 공유합니다. 파일은 시스템의 전역적인(모두 공유할 수 있는) 자원이므로 서로 다른 프로세스들끼리 데이터를 공유할 수 있습니다. 550 | 551 | - 장점 552 | - 데이터가 메모리에 올라와 있는 것처럼 간단하게 접근 할 수 있습니다. 553 | - 단점 554 | - 많은 데이터를 얼마나 오랫동안 메모리에 둘 것인지 컨트롤 할 수 없습니다. 555 | 556 | ------ 557 | 558 |
559 | 560 | # CPU 스케줄링 (CPU Scheduling) 561 | 562 | ## CPU 스케줄링이란? 563 | 564 | 단일 처리기 시스템에서는 한 순간에 하나의 프로세스만 실행될 수 있습니다. 즉, 나머지 프로세스는 CPU가 자유상태가 될 때까지 무기한 대기해야 하는 것이죠. 565 | 566 | 다중 프로그래밍의 목적은 CPU 이용률을 최대화하기 위해 항상 실행중인 프로세스가 존재하도록 하는 데 있습니다. 따라서 운영체제는 CPU를 점유한 프로세스에 대기가 발생할 때마다 그 프로세스로부터 CPU를 회수하여 다른 프로세스에게 할당하는 스케줄링을 시도합니다. 567 | 568 |
569 | 570 | ## CPU 스케줄링과 관련된 사전 지식 571 | 572 | ### CPU-입/출력 버스트 사이클(CPU I/O Burst Cycle) 573 | 574 | 먼저 프로세스가 실행되는 도중 CPU를 사용하지 않아 CPU가 쉬게 되는 상황에 대해 알아봅시다. 575 | 576 | 프로세스 실행은 **CPU 실행과 입/출력 대기의 사이클**로 구성됩니다. CPU가 필요할 때는 CPU를 집중적으로 사용하다가 입/출력 요청이 발생할 때는 CPU는 잠시 쉬고 입/출력을 대기하고 있는 것이죠. 577 | 578 | 프로세스가 실행되면 최초에는 CPU 버스트(CPU burst)로 시작하여 CPU를 집중적으로 사용합니다. 그러다 입/출력 요청이 발생하면 입/출력 버스트(I/O burst)로 교체되고, 이후 입출력이 끝나면 다시 CPU 버스트가 실행되며 이후에는 이 두 버스트가 반복적으로 발생하는 패턴을 보입니다. 579 | 580 | 입/출력 중심의 프로그램은 전형적으로 긴 입/출력 버스트와 짧은 CPU 버스트를 가지는 편이고, CPU 지향 프로그램은 전형적으로 짧은 입/출력 버스트와 긴 CPU 버스트를 가지는 편입니다. 따라서 CPU-입/출력 버스트 분포를 파악하여 CPU 스케줄링 알고리즘을 선택해야 합니다. 581 | 582 | ### CPU 스케줄러 (CPU Scheduler) 583 | 584 | CPU 할당을 기다리는 프로세스들이 모여있는 준비 완료 큐는 선입선출 큐, 우선순위 큐, 순서가 없는 연결 리스트 등으로 구현되어 있습니다. 585 | 586 | 입/출력 버스트 등에 의해 CPU가 유휴 상태가 될 때마다, 운영체제는 준비 완료 큐에 있는 프로세스 중 하나를 선택하여 실행해야 합니다. 이를 수행하는 것이 단기 스케줄러(Short term Scheduler 혹은, CPU 스케줄러)입니다. 587 | 588 | 준비 완료 큐에 있는 레코드들은 프로세스 제어 블록(PCB) 형태로 존재합니다. 589 | 590 | - PCB : 해당 프로세스 상태, 다음에 실행할 명령어의 주소, 프로세스 우선순위, 프로세스와 연관된 입/출력 장치 등에 대한 다양한 프로세스 정보를 수록한 블록 591 | 592 | ### 선점 스케줄링 (Preemptive Scheduling) 593 | 594 | 특정 프로세스에 CPU가 할당되어 사용되는 도중 다음과 같은 고민되는 순간이 생깁니다. 595 | 596 | >- 현재 실행중인 프로세스보다 우선 순위가 높은 프로세스가 준비 완료 큐에 들어왔을 때 해당 프로세스에게 CPU를 넘겨줘야 할까? 597 | >- 현재 프로세스가 아직 작업을 마치지 못했는데 자신에게 주어진 CPU 점유 시간을 다 채웠을 때는 어떻게 해야 할까? 598 | >- 🤔 599 | 600 | 위와 같은 상황에서 CPU를 계속 현재 프로세스에게 할당할 것인지, 아니면 다음 프로세스에게 넘겨줄 것인지(선점)를 결정하는 것에 따라 **선점/비선점 스케줄링**을 구분합니다. 601 | 602 | #### 선점 스케줄링 상황 603 | 604 | CPU 선점이 발생할 수 있는 조금 더 구체적인 상황을 생각해봅시다. 605 | 606 | 1. 한 프로세스가 실행 상태에서 대기 상태로 전환될 때(입/출력 요청이 들어왔을 때, 혹은 자식 프로세스의 종료를 기다리기 위해 wait을 호출할 때 등) 607 | 2. 프로세스가 실행 상태에서 준비 완료 상태로 전환될 때(인터럽트가 발생했을 때 등) 608 | 3. 프로세스가 대기 상태에서 준비 완료 상태로 전환될 때(입/출력 요청이 들어와 입/출력을 완료하고 입/출력이 종료될 때 등) 609 | 4. 프로세스가 종료할 때 610 | 611 | - 위의 상황 중 1, 4의 경우에는 무조건 다음 프로세스에게 CPU를 할당해야 겠죠. 하지만 2, 3의 경우에는 현재 실행중인 프로세스가 계속 CPU를 점유할지, 혹은 준비 완료 큐의 다른 프로세스에게 CPU를 넘겨줘야할 지 결정해야 합니다. 612 | - 만약 1, 4의 상황에서만 스케줄링이 발생할 경우, 즉 일단 CPU가 한 프로세스에 할당되면 해당 프로세스가 종료되거나 혹은 대기상태로 전환되기 전까지는 해당 프로세스가 무조건 CPU를 점유하게 되는 경우를 **비선점(non-preemptive)** 혹은 **협조적(cooperative)**이라고 합니다.(Microsoft Windows 3.1, Mac OS X 이전 Macintosh 운영체제에서 사용하던 스케줄링 기법) 613 | - 만약 1, 4뿐만 아니라 2, 3의 상황에서도 스케줄링이 발생할 경우, 즉 준비 완료 큐에 존재하는 다른 프로세스가 현재 프로세스를 제치고 CPU를 선점하는 경우를 **선점(preemptive)**이라고 합니다.(Windows 95 이후의 Windows 운영체제, Mac OS X 이후의 Macintosh 운영체제에서 사용하는 스케줄링 기법) 614 | 615 | 선점 스케줄링의 경우 공유 자료에 대한 접근에 주의를 기울여야 합니다. 또한 비선점 스케줄링보다 운영체제 커널 설계 등이 복잡할 수 있습니다. 616 | 617 | ### 디스패쳐 (Dispatcher) 618 | 619 | 디스패쳐는 CPU 스케줄러의 결정에 의해 선택된 프로세스에게 CPU를 넘겨주는 모듈입니다. 구체적인 디스패쳐의 역할은 다음과 같습니다. 620 | 621 | - 문맥 교환(Context Switching) 622 | - 사용자 모드로 전환 623 | - 프로그램을 다시 시작하기 위해 사용자 프로그램의 적절한 위치로 이동 624 | 625 | 위와 같은 작업을 수행하면서 소모하는 시간을 디스패치 지연(dispatch latency)이라고 합니다. 626 | 627 |
628 | 629 | ## CPU 스케줄링 기준 630 | 631 | CPU 스케줄링 알고리즘은 모두 서로 다른 특징을 갖고 있습니다. 특정 상황에서 더 나은 스케줄링 알고리즘을 선택하기 위해 다음과 같은 기준을 바탕으로 성능을 비교할 수 있습니다. 632 | 633 | 1. CPU 이용률 (CPU utilization) 634 | - CPU가 사용되는 정도 635 | 636 | 2. 처리량 (Throughput) 637 | - 단위 시간당 완료된 프로세스의 개수(작업량) 638 | 639 | 3. 총처리 시간 (Turnaround time) 640 | - 한 프로세스를 실행하는데 소요된 시간 641 | - 프로세스 완료 시간에서 프로세스 제출 시간을 마이너스 642 | - 준비 완료 큐에서 대기한 시간, CPU에서 실행하는 시간, 입/출력 시간 등을 포함 643 | 644 | 4. 대기 시간 (Waiting time) 645 | - 프로세스가 준비 완료 큐에서 대기하면서 보낸 시간의 합 646 | 647 | 5. 응답 시간 (Response time) 648 | - 대화식 시스템(interactive system)을 위한 기준 649 | - 응답이 시작되는 데까지 걸리는 시간 650 | 651 | 효율적인 스케줄링을 위해서는 CPU 이용률과 처리량는 최대화, 총처리 시간, 대기 시간, 응답 시간은 최소화하는 것이 바람직합니다. 652 | 653 |
654 | 655 | ## CPU 스케줄링 알고리즘 656 | 657 | 다양한 CPU 스케줄링 알고리즘을 소개합니다. 각 알고리즘의 특징과 장단점을 고려하여 프로그램에 맞는 알고리즘을 선택해야 합니다. 이 글에서 각 알고리즘의 성능은 평균 대기 시간으로 비교합니다. 658 | 659 | ### 선입 선처리 스케줄링 (First-Come, First-Served Scheduling) 660 | 661 | - CPU를 먼저 요청한 프로세스가 CPU를 먼저 할당받습니다. 즉, 준비 완료 큐에 들어온 순서대로 프로세스를 할당받습니다. 662 | - CPU가 자유상태가 되면 준비 완료 큐의 가장 앞에 있는 프로세스에게 CPU를 할당하고, 준비 완료 큐는 가장 앞에 위치한 프로세스를 제거합니다. 663 | - 이 때, 준비 완료 큐는 선입선출(FIFO) 큐로 관리됩니다. 664 | - 비선점형 스케줄링 기법입니다. 665 | - 장점 : 구현이 쉽습니다. 666 | - 단점 667 | - 최소 평균 대기 시간을 보장하지 않습니다. 668 | - 하나의 긴 프로세스가 CPU를 점유할 경우 모든 다른 프로세스들이 CPU 양도를 기다리는 호위효과(convoy effect)가 발생합니다. -> CPU와 장치 이용률 저하 669 | 670 | #### 스케줄링 시뮬레이션 671 | 672 |

673 |

674 | 675 | > 평균대기시간 = (0+24+27)/3 = 17 676 | 677 |
678 | 679 | ### 최단 작업 우선 스케줄링 (Shortest-Job-First Scheduling) 680 | 681 | - 가장 작은 CPU 버스트를 가진 프로세스가 CPU를 먼저 할당받습니다. 682 | - 단, 두 프로세스가 동일한 길이의 다음 CPU 버스트를 가질경우 선입 선처리 스케줄링을 적용합니다. 683 | - 선점형, 비선점형 스케줄링을 모두 적용할 수 있습니다. 684 | - 장점 : 최소 평균 대기 시간을 보장하므로 **최적** 스케줄링 기법입니다. 685 | - 단점 : 다음 CPU 버스트 길이를 미리 파악하기 어렵습니다.(다음 CPU 버스트 길이가 이전의 버스트 길이와 유사할 것이라고 기대한 뒤 근사 값을 계산하는 방법이 있습니다.) 686 | 687 | #### 비선점형 스케줄링 시뮬레이션 688 | 689 |

690 |

691 | 692 | > 평균대기시간 = (3+16+9+0)/4 = 7 693 | 694 | #### 선점형 스케줄링(최소 잔여 시간 우선 스케줄링) 시뮬레이션 695 | 696 |

697 |

698 | 699 | > 평균대기시간 = ((10-1)+(1-1)+(17-2)+(5-3))/4 = 6.5 700 | 701 |
702 | 703 | ### 우선순위 스케줄링 (Priority Scheduling) 704 | 705 | - 각 프로세스는 특정 기준에 의해 우선순위가 부여되어 있습니다. 이 기준에 의해 우선순위가 가장 높은 프로세스가 CPU를 먼저 할당받습니다. 706 | - 단, 우선순위가 같은 프로세스들은 선입 선처리 스케줄링을 적용합니다. 707 | - SJF 스케줄링 역시 우선순위 스케줄링의 한 종류라고 볼 수 있습니다. 708 | - 우선순위의 기준으로는 시간 제한, 메모리 요구, 열린 파일의 수, 평균 입/출력 버스트의 평균 CPU 버스트의 비율, 프로세스의 중요도, 비용, 정치적인 요인 등이 있습니다. 709 | - 선점형, 비선점형 스케줄링을 모두 적용할 수 있습니다. 710 | - 선점형 : 준비 완료 큐에 새로운 프로세스가 들어오면 현재 진행중인 프로세스와 우선순위를 비교하여 우선순위가 더 높은 프로세스가 CPU를 선점 711 | - 비선점형 : 현재 진행중인 프로세스를 계속 진행하되 새로 들어온 높은 우선순위의 프로세스는 준비 완료 큐의 머리 부분에 삽입 712 | - 장점 : 우선순위를 고려할 수 있습니다. 713 | - 단점 : 낮은 우선순위 프로세스들이 CPU를 무한히 대기하는 문제(**무한 봉쇄(indefinite blocking)** 혹은 **기아 상태(starvation)**)가 발생할 수 있습니다. 714 | - 위의 문제를 해결하는 방법으로 오랫동안 대기하는 프로세스들의 우선순위를 점진적으로(특정 시간마다) 증가시켜주는 기법(**노화(aging)**)을 적용할 수 있습니다. 715 | 716 | #### 선점형 스케줄링 시뮬레이션 717 | 718 |

719 |

720 | 721 | > 평균대기시간 = (6+0+16+18+1)/5 = 8.2 722 | 723 |
724 | 725 | ### 라운드 로빈 스케줄링 (Round-Robin Scheduling) 726 | 727 | - 사전에 CPU 시간 할당량(time quantum) 또는 시간 조각(time slice)를 설정하고, 한 프로세스에게 지정된 시간 할당량만큼의 CPU 점유 시간을 부여하는 스케줄링 방법입니다. 728 | - 시간 할당량만큼 CPU를 점유한 프로세스에게는 인터럽트가 발생하도록 타이머를 설정한 후, 프로세스를 디스패치합니다. 729 | - 시분할 시스템을 위해 설계된 기법입니다. 730 | - 이 때, 준비 완료 큐는 선입선출(FIFO) 큐로 관리됩니다. 731 | - 프로세스는 주어진 시간 할당량 이내에 작업을 완료할 수도 있고 완료하지 못할 수도 있습니다. 이 때는 다음과 같이 처리합니다. 732 | - 프로세스의 CPU 버스트 < 시간 할당량 : 프로세스가 종료된 이후 자신이 자발적으로 CPU를 방출 733 | - 프로세스의 CPU 버스트 > 시간 할당량 : 타이머가 끝나고 인터럽트가 발생되면 문맥 교환이 일어나고 실행하던 프로세스는 준비 완료 큐의 꼬리에 위치 734 | - 선점형 스케줄링 기법입니다. 735 | - 장점 : 프로세스가 n개 존재하고 각 프로세스 당 시간 할당량이 q라고 가정한다면, 각 프로세스는 다음 시간 할당까지 최대 (n-1) * q 이상을 대기하지 않음을 보장할 수 있습니다. 736 | - 단점 : 시간 할당량의 크기 설정에 따라 알고리즘의 성능이 크게 영향을 받습니다. 737 | - 시간 할당량이 지나치게 크면 선입 선처리 스케줄링 기법과 같아질 수 있습니다. 738 | - 시간 할당량이 지나치게 작으면 문맥 교환 오버헤드가 커져 총처리 시간이 증가합니다. 739 | 740 | #### 스케줄링 시뮬레이션 (시간 할당량 : 4) 741 | 742 |

743 |

744 | 745 | > 평균대기시간 = (10+4+7)/3 = 7 746 | 747 |
748 | 749 | ### 다단계 큐 스케줄링 (Multilevel Queue Scheduling) 750 | 751 | - 준비 완료 큐를 다수의 별도의 큐로 분류하여 각 큐마다 제각각의 스케쥴링 알고리즘을 적용하는 방법입니다. 752 | - 프로세스는 포어그라운드(foreground, 대화형) 프로세스와 백그라운드(background, 일괄처리) 프로세스로 구분될 수 있습니다. 일반적으로 대화형 시스템을 위해 포어그라운드 프로세스가 우선순위를 갖는 경우가 많습니다. 753 | - 따라서 프로세스의 메모리 크기, 프로세스의 우선순위, 프로세스 유형, 프로세스 특성에 따라 각각의 프로세스는 특정 큐에 할당될 수 있습니다. 단, 프로세스는 큐 간 이동할 수는 없습니다. 754 | - 각 큐는 낮은 우선순위의 큐보다 절대적인 우선순위를 가집니다. 또한 큐들 사이에 시간을 나누어 CPU를 사용하기도 합니다. 755 | - 선점형 스케줄링 기법입니다. 756 | 757 | ### 다단계 피드백 큐 스케줄링 (Multilevel Feedback Queue Scheduling) 758 | 759 | - 다단계 큐 스케쥴링에서 프로세스가 큐들 사이를 이동하는 것을 허용한 방법입니다. 760 | - 특정 프로세스가 CPU를 너무 많이 점유할 경우, 해당 프로세스를 낮은 우선순위 큐로 이동시킬 수 있습니다. 761 | - 또한 큐에서 너무 오래 대기하는 프로세스는 높은 우선순위 큐로 이동(노화 기법)시킬 수 있습니다. 762 | - 역시 각 큐는 낮은 우선순위의 큐보다 절대적인 우선순위를 가지고 큐들 사이에 시간을 나누어 CPU를 사용할 수도 있습니다. 763 | - 선점형 스케줄링 기법입니다. 764 | 765 |
766 | 767 | ## 다중 처리기 스케줄링 (Multiple-Processor Scheduling) 768 | 769 | 위에서 정리한 CPU 스케줄링 기법은 단일 처리기 시스템 하에서 하나의 CPU를 어떻게 스케줄링할 것인지 결정했습니다. 하지만 CPU가 여러개라면 여러개의 CPU를 여러 프로세스에게 할당해야하는 더 복잡한 문제가 발생합니다. 다중 처리기 시스템에서는 CPU 스케줄링을 어떻게 결정할까요? 또한 무엇을 고려해야 할까요? 770 | 771 | ### 다중 처리기 시스템에서의 스케줄링 결정 대상 772 | 773 | 1. 비대칭 다중 처리(asymmetric multiprocessing) 774 | 775 | - 주 서버라는 하나의 처리기가 모든 스케줄링 결정을 내립니다. 776 | - 다른 서브 처리기들은 주 서버의 결정에 따라 사용자의 코드만을 수행합니다. 777 | - 주 서버 처리기만 시스템 자료 구조에 접근하므로 자료 공유로인한 문제가 발생하지 않습니다. 778 | 779 | 2. 대칭적 다중 처리(symmetric multiprocessing, SMP) 780 | 781 | - 각 처리기가 독자적으로 스케줄링을 합니다. 782 | - 각 처리기는 공통의 준비 완료 큐에서 프로세스를 선택할 수도 있고, 자신만의 독자적인 준비 완료 큐를 구성할 수도 있습니다. 783 | - 다중 처리기가 공동의 시스템 자료 구조에 접근하므로 자료 공유 문제를 고려해야 합니다. 784 | - 또한 공통의 준비 완료 큐를 사용할 경우 다중 처리기가 공통된 프로세스를 선택하지 않도록 조심해야 합니다. 785 | 786 | ### 다중 처리기 시스템에서의 스케줄링 쟁점 787 | 788 | - 처리기 친화성 (Processor Affinity) 789 | 790 | 프로세스가 여러 처리기로 이동하게 될 경우 캐시 메모리를 채우고 비우는 오버헤드가 발생합니다. 791 | 792 | 따라서 한 처리기에서 다른 처리기로의 이주를 피하고, 대신 같은 처리기에서 프로세스를 실행시키려고 하는 현상을 보이는데 이 현상을 처리기 친화성이라고 합니다. 793 | 794 | - 부하 균등화 (Load Balancing) 795 | 796 | 모든 처리기 사이의 부하가 고르게 배분되도록 하는 것을 말합니다. 대칭적 다중 처리 시스템에서 여러 처리기를 최적으로 활용하기 위해서는 부하 균등화가 잘 이루어져야 합니다. 797 | 798 | 부하 균등화는 대칭적 다중 처리 시스템의 각 처리기가 공통의 준비 완료 큐가 아닌 자기 자신만의 큐를 가지고 있을 때 적용 가능합니다. 한 처리기가 과부하 상태일 때 여유로운 처리기로 프로세스를 이동시키는 것을 push, 여유로운 처리기에서 과부하 처리기의 프로세스를 이주시키는 것을 pull 이라 합니다. 799 | 800 | 단, 부하 균등화는 위에서 소개한 처리기 친화성과 상충되므로 사전에 부하 불균형 상태에 대한 적절한 정의가 이루어져야 합니다. 801 | 802 | - 대칭적 다중 쓰레딩 (Symmetric Multithreading) 803 | 804 | 대칭적 다중 처리 시스템은 다수의 물리적인 처리기를 제공하는 것을 말합니다. 이와 달리 동일한 물리 처리기 상에 다수의 논리적인 처리기를 제공하여 다수의 쓰레드가 동시에 실행되도록 하는 것을 **대칭적 다중 쓰레딩(SMT, 하이퍼쓰레딩 기술(hyperthreading technology))**라고 합니다. 805 | 806 | 논리적인 처리기는 하나의 물리적인 처리기 내부에 여러개 존재할 수 있습니다. 이 논리적인 처리기들은 캐시 메모리, 버스 등과 같은 자신이 속한 물리적인 처리기의 자원을 공유하며 사용합니다. 807 | 808 |
809 | 810 | 811 | # Deadlock 교착상태 812 | 813 | ## 교착상태란? 814 | 815 | 한 프로세스 집합 내의 모든 프로세스가 그 집합 내의 다른 프로세스에 의해서만 발생될 수 있는 사건을 기다리는 상황이 발생하여, 프로세스들이 모두 무한정 대기에 빠지는 것을 말합니다. 816 | 817 | > 예를 들어봅시다. 프로세스는 자원을 사용하기 위해 **요청**, **사용**, **방출** 순서를 지켜야합니다. 818 | > 3개의 CD RW 드라이브를 가진 시스템에서 3개의 프로세스가 각각의 CD RW 드라이브를 사용하고 있는 상태라고 가정합니다. 만약 이 상황에서 3개의 프로세스가 또 다른 드라이브를 요청할 경우, 세 프로세스는 교착상태에 빠지게 됩니다. 모든 프로세스는 다른 대기중인 프로세스에 의해 드라이브가 방출되어야지만 대기에서 빠져나올 수 있기때문입니다. 819 | 820 |
821 | 822 | ## 교착상태의 특징 823 | 824 | ### 교착상태 발생의 필요 조건 825 | 826 | 교착상태는 한 시스템에 다음 네 가지 조건이 동시에 성립될 때 발생할 수 있습니다. 827 | 828 | 1. 상호 배제(Mutual exclusion) 829 | - 최소한 하나의 자원이 비공유 모드(하나의 자원은 한 번에 한 프로세스만 사용할 수 있음)로 점유되어야 합니다. 830 | - 다른 프로세스가 그 자원을 요청할 경우, 요청 프로세스는 자원이 방출될 때까지 대기해야 합니다. 831 | 2. 점유하며 대기(Hold-and-wait) 832 | - 프로세스는 최소한 하나의 자원을 점유한 상태로, 현재 다른 프로세스에 의해 점유된 자원을 추가로 얻기 위해 대기해야 반드시 합니다. 833 | 3. 비선점(No preemption) 834 | - 자원이 강제적으로 방출될 수 없습니다. 835 | - 점유하고 있는 프로세스가 태스크를 종료한 후 그 프로세스에 의해 자발적으로만 방출될 수 있습니다. 836 | 4. 순환 대기(Circular wait) 837 | - 대기하고 있는 프로세스 집합 {p0, p1, ..., pn}에서 p0은 p1이 점유한 자원을 대기하고, p1은 p2가 점유한 자원을 대기하고, pn은 p0이 점유한 자원을 대기하는 것과 같은 상황입니다. 838 | - 즉, 대기하는 방향이 순환하는 형태입니다. 839 | 840 | ### 자원 할당 그래프(Resource-Allocation Graph) 841 | 842 | 교착상태는 정점(vertex, V)과 간선(edge, E) 집합으로 표현할 수 있습니다. 843 | 844 | - 정점 845 | - 시스템 내의 모든 활성 프로세스(원으로 표현) 846 | - 시스템 내의 모든 자원 유형(사각형으로 표현) 847 | - 간선 848 | - 프로세스의 자원 요청 관계(프로세스에서 자원으로의 화살표로 표현) 849 | - 자원의 프로세스 할당 관계(자원에서 프로세스로의 화살표로 표현) 850 | 851 | ![resource-allocation-graph](./img/resource-allocation-graph1.png) 852 | 853 | ![resource-allocation-graph](./img/resource-allocation-graph2.png) 854 | 855 |
856 | 857 | ## 교착상태 처리 방법 858 | 859 | 원칙적으로 교착상태 문제를 처리하는 데에는 다음과 같은 세 가지 방법이 존재합니다. 860 | 861 | - 시스템이 교착상태가 되지 않도록 보장하기 위해 교착 상태를 예방하거나 회피하는 프로토콜을 이용합니다. 862 | - 시스템이 교착상태가 되도록 허용한 다음 회복시킵니다. 863 | - 문제를 무시하고, 교착상태가 시스템에서 발생하지 않은 척 합니다. 864 | 865 | 놀랍게도 UNIX와 Windows를 비롯한 대부분의 운영체제는 세 번째 방법을 사용합니다. 이는 드물게 발생하는 교착상태에 대해 처리 비용과 오버헤드가 큰 교착상태 예방, 회피 및 탐지, 복구 알고리즘을 적용하는 것보다 수작업으로 시스템을 중지하고 재시작하는 것이 더 낫다고 판단하기 때문입니다. 866 | 867 |
868 | 869 | ### 교착상태 예방(Deadlock Prevention) 870 | 871 | 교착상태를 예방하기 위해서는 앞서 언급한 4가지의 교착 상태 발생 필요 조건 중 적어도 하나가 성립하지 않도록 보장해야 합니다. 872 | 873 | #### 1. 상호 배제 874 | 875 | 상호 배제 조건은 공유가 불가능한 자원에 대해서는 반드시 성립해야 합니다. 따라서 근본적으로 동시 접근을 허용할 수 없는 자원이라면 상호배제 조건을 거부함으로써 교착 상태를 예방하는 것은 불가능합니다. 876 | 877 | #### 2. 점유하며 대기 878 | 879 | 점유하며 대기 조건의 성립을 막기 위해, 프로세스가 자원을 요청할 때는 다른 자원들을 점유하지 않을 것을 보장해야 합니다. 이를 위한 방법으로는 2가지가 존재합니다. 880 | 881 | - 프로세스가 실행되기 전 자신이 필요로하는 모든 자원을 최초에 한 번에 요청하고 할당받습니다. 882 | - 프로세스가 자원을 전혀 갖고 있지 않을 때만 자원을 요청할 수 있도록 허용합니다. 883 | 884 | > 예를 들어봅시다. DVD 드라이브로부터 자료를 받아 디스크 파일로 저장하고 이를 프린터로 출력하는 프로세스가 존재합니다. 전자의 방법을 적용할 경우 프로세스는 초기에 DVD 드라이브, 디스크 파일, 프린터를 요청해야 합니다. 후자의 방법을 적용할 경우 프로세스는 DVD 드라이브, 디스크 파일을 먼저 요청하여 사용한 뒤 이를 방출하고 나서 프린터를 요청하고 사용할 수 있습니다. 885 | 886 | 두 방법에는 모두 단점이 존재합니다. 전자의 경우 많은 자원들이 한꺼번에 할당된 후 오랜 기간 동안 사용되지 않고 점유될 수 있기때문에 **자원의 이용도가 낮을 수 있습니다**. 후자의 경우 자신이 필요한 자원 중 최소 하나 이상이 항상 다른 프로세스에게 할당되어 있기 때문에 **기아 상태**에 빠질 수 있습니다. 887 | 888 | #### 3. 비선점 889 | 890 | 비선점 조건의 성립을 막기 위해서는, 어떤 자원을 점유하고 있는 프로세스가 다른 자원을 요청했지만 해당 자원을 당장 프로세스에게 할당할 수 없는 경우(즉, 대기가 발생할 경우) 프로세스가 원래 점유하고 있던 자원이 선점될 수 있도록 합니다. 891 | 892 | #### 4. 순환 대기 893 | 894 | 순환 대기 조건의 성립을 막기 위해서는, 모든 자원 유형들에게 순서를 부여하여 프로세스가 열거된 순서대로 자원을 요청하도록 요구해야 합니다. 895 | 896 |
897 | 898 | ### 교착상태 회피(Deadlock Avoidance) 899 | 900 | 위의 방법들로 교착상태를 예방할 수 있지만, 장치 이용률이 저하되고 시스템 처리율이 감소된다는 한계가 존재합니다. 901 | 902 | 다른 접근으로는 **프로세스가 일생 동안 요청하고 사용할 자원에 대한 정보를 사전에 제공받아, 교착상태를 미리 예측**하는 방법이 있습니다. 이를 위해서는 현재 가용 자원, 현재 각 프로세스에게 할당된 자원, 각 프로세스가 앞으로 요청하거나 방출할 자원을 고려해야 합니다. 903 | 904 | 2가지의 교착상태 회피 알고리즘이 존재합니다. 이 알고리즘을 통해 시스템 **안전 상태**(프로세스들이 요청하는 모든 자원을 교착 상태를 발생시키지 않고 할당해줌)를 판단할 수 있습니다. 시스템이 불안전 상태라고 할지라도 교착상태에 빠지지 않을 수 있지만, 교착상태에 빠진다면 불안전 상태에 존재하게 됩니다. 따라서 시스템을 안전 상태로 유지한다면 교착상태를 예방할 수 있습니다. 905 | 906 | #### 자원 할당 그래프 알고리즘 907 | 908 | 시스템의 각 자원 유형 별로 *단 하나의 인스턴스*만 존재하는 경우 자원 할당 그래프를 조금 변형시켜 교착 상태를 예견할 수 있습니다. 909 | 910 | 요청 간선과 할당 간선에 **예약 간선**이라는 새로운 유형을 도입합니다. 예약 간선은 프로세스가 미래에 해당 자원을 요청할 것이라는 의미를 내포합니다. 따라서 프로세스 실행 전 모든 예약 간선을 자원 할당 그래프에 명시해둔다면 교착 상태가 발생할 것을 사전에 예측할 수 있습니다. 911 | 912 | ![resource-allocation-graph-algorithm](./img/resource-allocation-graph-algorithm.png) 913 | 914 | 예약 간선을 할당 간선으로 변환시켜도 자원 할당 그래프에 사이클이 형성되지 않을 때에만 자원을 할당한다면 교착 상태가 발생하는 것을 피할 수 있습니다. 915 | 916 | #### 은행원 알고리즘(Banker's Algorithm) 917 | 918 | 시스템의 각 자원 유형 별로 *여러개의 인스턴스*가 존재하는 경우 적용할 수 있는 알고리즘입니다. 919 | 920 | 이름에서 볼 수 있듯이 은행에서 돈을 빌리려는 다수의 고객이 존재할 때, 은행이 파산하지 않고 모든 고객에게 돈을 빌려주는 원리를 이용합니다. 921 | 922 | > 예를 들어 봅시다. 100달러를 보유하고 있는 은행에 3명의 고객이 찾아와 각각 60달러, 40달러, 50달러씩 대출하기를 신청했습니다. 923 | > 은행은 먼저 고객1에게는 20달러를, 고객2와 고객3에게는 30달러씩 빌려줍니다. 은행은 수중에 20달러가 남습니다. 924 | > 이후 고객2에게 남은 10달러를 빌려주고 기다립니다. 고객2가 40달러를 상환하면 은행은 수중에 50달러가 남습니다. 925 | > 이후 고객1에게 남은 40달러를 빌려주고 기다립니다. 고객1이 60달러를 상환하면 은행은 수중에 70달러가 남습니다. 926 | > 이후 고객3에게 남은 20달러를 빌려주고 기다립니다. 고객3이 50달러를 상환하면 은행은 파산하지 않고 모든 고객게에 돈을 빌려줄 수 있습니다. 927 | > 하지만 3번째 단계에서 은행이 고객1에게 남은 20달러를 모두 빌려줬다면 고객 중 상환할 수 있는 사람은 없고, 모두 대출을 받기 위해 기다려야 하는 상태에 빠지게 되어 파산하게 됩니다. -> 교착상태 928 | 929 | 이 방법과 같이 시스템은 **프로세스의 자원 요청을 허가**했을 때 시스템이 **안전 상태에 머무른다면 요청을 들어주고** 그렇지 않다면 프로세스를 대기시킵니다. 안전 상태에서 머무를 수 있도록 하는 안전 순서열이 존재한다면 시스템의 교착상태를 막을 수 있습니다. 930 | 931 | 이를 구현하기 위해 다음과 같은 자료구조가 필요합니다 932 | 933 | - 가용(Available) : 각 종류의 자원이 현재 몇 개가 가용한지 나타내는 벡터 934 | - `Available[j] = k` : 현재 Rj를 k개 사용할 수 있음 935 | - 최대(Max) : 각 프로세스가 최대로 필요로하는 자원의 개수를 나타내는 행렬 936 | - `Max[i, j] = k` : Pi가 Rj를 최대 k개 요청할 수 있음 937 | - 할당(Allocation) : 각 프로세스에게 현재 할당되어 있는 자원의 개수를 나타내는 행렬 938 | - `Allocation[i,j] = k` : 현재 Pi가 Rj를 k개 사용하고 있음 939 | - 요구(Need) : 각 프로세스가 향후 요구할 수 있는 자원의 개수를 나타내는 행렬 940 | - `Need[i,j] = k` : 향후 Pi가 Rj를 k개까지 요청할 수 있음 941 | - `Max[i, j] - Allocation[i,j] = Need[i,j]` 942 | 943 | ##### 안정성 알고리즘(Safty Algorithm) 944 | 945 | 시스템이 안전한지 판단하는 알고리즘 입니다. n은 프로세스 수를, m은 자원 종류의 수를 나타냅니다. 946 | 947 | 1. Work(향후 사용 가능한 자원 수)와 Finish(자원을 모두 사용하여 작업이 끝난 프로세스 수)는 각각 크기가 m과 n인 벡터이다. Work = Available로 초기화한다. 프로세스의 번호를 나타내는 i를 대상으로 Finish[i] = false로 초기화한다. 948 | 2. 두 조건을 만족시키는 i를 찾는다. 만약 그러한 i를 찾지 못하면 step 4로 간다. 949 | - Finish[i] == false 950 | - Needi <= Work 951 | 3. 아래 두 연산을 수행하고 step 2로 간다. 952 | - Work = Work + Allocationi 953 | - Finish[i] = true 954 | 4. 모든 i에 대해 Finish[i] == true이면 이 시스템은 안전 상태에 있다. 955 | 956 | ![banker's-algorithm](./img/banker's-algorithm.png) 957 | 958 |
959 | 960 | ### 교착 상태 탐지(Deadlock Detection) 961 | 962 | 시스템이 교착상태 예방이나 교착상태 방지 알고리즘을 사용하지 않는다면 결국에는 교착상태가 발생하게 됩니다. 이러한 환경에서는 교착상태가 발생했는지 확인하기 위한 시스템 상태 검사 알고리즘과 교착 상태로부터 회복하는 알고리즘이 필요합니다. 963 | 964 | 교착상태 탐지는 자원 유형 별 개수에 따라 다른 방법을 적용합니다. 965 | 966 | 1. 자원 유형이 한 개씩 있는 경우 967 | 968 | 자원 할당 그래프를 변형시킨 대기 그래프를 활용하여 교착상태를 탐지할 수 있습니다. 대기 그래프가 사이클을 포함할 경우 시스템에 교착상태가 존재한다고 판단할 수 있습니다. 969 | 970 | ![wait-for-graph](./img/wait-for-graph.png) 971 | 972 | 2. 자원 유형 별 자원이 여러개 있는 경우 973 | 974 | 교착상태 회피 알고리즘의 은행원 알고리즘과 유사합니다. 가용(Available), 할당(Allocation), 요청(Request) 자료구조를 이용하여 모든 프로세스가 요구하는 자원을 충족시켜줄 안전 순서열이 존재하는지 여부를 파악합니다. 975 | 976 | **교착상태 발생 빈도**와 **교착상태 발생 시 몇 개의 프로세스가 연루되는지**에 따라 교착상태 탐지 알고리즘을 실행시킬 수 있습니다. 프로세스의 요청이 즉시 만족되지 않을 때마다 탐지 알고리즘을 실행시킨다면, 교착상태를 야기한 프로세스를 파악할 수 있지만 오버헤드가 크게 발생할 수 있다는 딜레마가 존재합니다. 977 | 978 |
979 | 980 | ### 교착 상태로부터 회복 981 | 982 | 교착상태에서 빠져나오기 위해 시스템은 두 가지 방법을 시도할 수 있습니다. 첫 번째 방법은 프로세스를 중지시킴으로써 순환 대기를 깨뜨리는 것이고, 두 번째 방법은 프로세스로부터 자원을 선점하는 것입니다. 983 | 984 | 한가지 중요한 것은 탐지와 회복 과정에서 이러한 알고리즘을 실행시키기 위한 비용 뿐만 아니라, 교착상태가 발생했을 때 부가적으로 나타나는 손실을 고려해야 한다는 것입니다. 985 | 986 | #### 프로세스 종료(Process Termination) 987 | 988 | - 교착상태의 프로세스들을 모두 중지 989 | - 프로세스가 그동안 연산한 내용이 모두 폐기되므로 비용이 큼 990 | - 교착상태에서 빠져나올 때까지 한 프로세스씩 중지 991 | - 각 프로세스가 중지될 때마다 교착 상태 탐지 알고리즘을 호출해야 하므로 오버헤드가 유발됨 992 | 993 | 프로세스를 중간에 중지시키는 것은 결코 쉬운 방법은 아닙니다. 프로세스가 작업하던 파일을 손상시킬 수도 있고, 또 어떤 프로세스를 중지시킬 지 결정하는 데에도 비용이 들어갑니다. 994 | 995 | #### 자원 선점(Resource Preemption) 996 | 997 | 교착상태를 해결하기 위해 선점을 할경우 **희생자를 선택**해야 하고, **롤백 상태를 선택**해야 하며, **기아 상태**가 발생하지 않도록 해야합니다. 998 | 999 |
1000 | 1001 | ## 결론 1002 | 1003 | 다양한 교착상태 방지 기법이 존재하지만 어떤 방법도 단독으로 사용하기에는 한계가 존재합니다. 따라서 최적의 해결책을 선택하기 위해서는 위의 기본 방법들을 적절하게 조합하여 사용해야 합니다. 1004 | 1005 | --- 1006 |
1007 | 1008 | # Race Condition 1009 | ## Race Condition이란? 1010 | 1011 | **여러 프로세스(혹은 쓰레드)가 동시에 공통 자원을 읽거나 쓰는 동작을 하고 그 실행 결과가 접근이 발생한 순서에 의존하는 상황**을 경쟁 상태(race condition)라고 합니다. 경쟁상태에서는 실행 결과가 개발자의 의도와 다르게 나올 수 있습니다. 다음 Producer-Consumer 예시를 살펴봅시다.

1012 | 쓰레드 A는 공유버퍼에 새항목을 추가하고 전역변수 counter의 값을 1 증가시키는 작동을 합니다. 쓰레드 B는 공유 버퍼에서 한 항목을 꺼내고 전역변수 counter의 값을 1 감소시키는 작동을 합니다. 1013 | 1014 | ```C 1015 | // Thread A(Producer) 1016 | while(true){ 1017 | /* Produce an item in next produced */ 1018 | while(count == BUFFER_SIZE) 1019 | ; /* do nothing */ 1020 | 1021 | buffer[in] = next_produced; 1022 | in = (in + 1 ) % BUFFER_SIZE; 1023 | count++; 1024 | } 1025 | 1026 | // Thread B(Consumer) 1027 | while(true){ 1028 | while(count == 0) 1029 | ; /* do nothing */ 1030 | 1031 | next_consumed = buffer[out]; 1032 | out = (out +1) % BUFFER_SIZE; 1033 | count--; 1034 | /* consume the item in next_consumed */ 1035 | } 1036 | ``` 1037 | 1038 | 현재 카운터의 값이 5라면 두 쓰레드가 각각 한번 실행된 결과는 원래 값인 5가 나와야 합니다. 하지만, 아래와 같은 순서로 번갈아 실행되면 counter는 개발자의 의도와 달리 4 또는 6 이 될 수 있습니다. 1039 | 1040 |
1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1057 | 1058 | 1059 | 1065 | 1066 |
Thread AThread B
고급어counter = counter + 1;counter = counter - 1;
기계어register1 = counter;
register1 = register1 + 1;
counter = register1;
register2 = counter;
register2 = register2 - 1;
1056 | counter = register2;
T0: Thread A가 register1 = counter 수행 {register1 = 5}
1060 | T1: Thread A가 register1 = register1+1 수행 {register1 = 6}
1061 | T2: Thread B가 register2 = counter 수행 {register2 = 5}
1062 | T3: Thread B가 register2 = register2 1 수행 {register2 = 4}
1063 | T4: Thread A가 counter = register1 수행 {counter = 6}
1064 | T5: Thread B가 counter = register2 수행 {counter = 4}
1067 |
1068 | 1069 | 위와 같이 Race condition에서는 비정상적인 결과가 나올 수 있습니다. 이 문제는 항상 발생하는 게 아니라 기계어 레벨에서 특정한 순서로 수행되었을 때만 발생하게 되므로 디버깅 시에는 문제점이 전혀 보이지 않아 고치기가 매우 어렵습니다. 그래서 멀티프로세스 프로그래밍을 할 경우에 Race condition 방지를 위해 **프로세스 동기화(한번에 하나의 프로세스만 자원에 접근하도록 하는 것)** 를 해야합니다. 1070 | 1071 | ## 임계구역(Critical Section) 1072 | 1073 | 프로세스 동기화를 위해 우리는 임계구역에 대해 알 필요가 있습니다. 임계구역이란 **다른 프로세스와 공유하는 자원에 접근하는 코드 세그먼트**를 말합니다. 프로세스 동기화는 임계구역에 한번에 하나의 프로세스만 들어갈 수 있도록 함으로써 구현할 수 있습니다. 임계 구역 진입 통제를 위해 작성하는 코드는 다음과 같이 크게 네부분으로 나뉩니다. 1074 | 1075 | ```c 1076 | while(true){ 1077 | // entry section: 임계구역 진입 요청 코드 1078 | 1079 | // critical section: 임계 구역 1080 | 1081 | // exit section: 임계구역에서 빠져나오는 코드 1082 | 1083 | // remainder section: 나머지 코드 총칭 1084 | } 1085 | ``` 1086 | 1087 | ### 임계구역 문제에서 고려해야할 요구조건들 1088 | 1089 | 프로세스들이 데이터를 협력적으로 공유하기 위해서 자신들의 활동을 동기화 할 때 사용할 수 있는 프로토콜을 설계하는 것을 **임계구역 문제**라고 하고 이에 대한 해결안은 다음과 같은 세가지 요구조건을 충족해야 합니다. 1090 | 1091 | 1. **상호 배제(mutual exclusion)**: 프로세스 Pi가 자기의 임계구역에서 실행된다면 다른 프로세스 들은 그들 자신의 임계구역에서 실행될 수 없다. 1092 | 2. **진행(progress)**: 임계구역에서 실행되는 프로세스가 없고 임계구역으로 진입하려고 하는 다른 프로세스들이 있다면, 기다리는 프로세스들만 다음에 누가 그 임계구역으로 진입할 수 있는지를 결정하는 데 참여가능하며 이 선택은 무한정 연기될 수 없다. 1093 | 3. **한정된 대기(bounded waiting)***: 프로세스가 자기의 임계구역에 진입하려는 요청을 한 후부터 그 요청이 허용될 때까지 다른 프로세스들이 그들 자신의 임계구역에 진입하도록 허용되는 횟수에 한계가 있어야 한다. 1094 | 1095 | 이러한 요구조건들이 모두 충족되어야 프로세스 동기화가 정상작동할 수 있으며 앞으로 살펴볼 여러 동기화 기법들은 모두 이 요구조건을 충족합니다. 1096 | 1097 | ## 동기화 기법들 1098 | 1099 | 동기화를 구현하는 다양한 기법들이 존재합니다. 1100 | 1101 | - 소프트웨어 기반 해결책: 알고리즘이 상호 배제를 보장하기 위해 운영체제나 특정 하드웨어 명령어의 특별한 지원을 포함하지 않는 방법) 1102 | - Peterson's Solution: 임계 구역에 대한 고전적인 소프트웨어 기반 해결책, 현대 컴퓨터 구조에서 올바르게 실행됨을 보장하지 않음, 이론적으로 임계구역 문제의 세가지 요구조건을 충족하는 소프트웨어 설계시 필요한 복잡성을 잘 설명하는 기법 (https://dailyheumsi.tistory.com/132) 1103 | - 하드웨어 기반 해결책: 운영체제나 특정 하드웨어 명령어의 특별한 지원을 활용하는 방법 1104 | - 메모리 장벽 1105 | - 하드웨어 명령어(test_and_set(), compare_and_swap()) 1106 | - 원자적 변수 1107 | - Mutex Locks: 응용 프로그래머가 사용할 수 있도록 운영체제 설계자들이 제공하는 상위 수준 소프트웨어 도구 중 가장 간단한 형태. 1108 | - Semaphore: mutex와 유사하지만 프로세스들이 자신의 행동을 더 정교하게 동기화 할 수 있는 방법을 제공하는 도구 1109 | - Monitor 1110 | --- 1111 |
1112 | 1113 | # 세마포어와 뮤텍스 1114 | 1115 | ## 📌 멀티스레드 프로그래밍에서의 동기화 문제 1116 | ![image](https://user-images.githubusercontent.com/55073084/134780551-083aa7bc-1c97-44cf-b2d8-701dcbb2ff53.png) 1117 | 1118 | 멀티스레드가 구현된 프로그램 안에서 두 개 이상의 스레드가 동시에 어떤 기능을 수행함에 있어 두개의 쓰레드가 만약 어떤 자원(변수) 같이 공유해서 사용하는 경우가 있다고 가정 1119 | 1120 | 1121 | 각각의 쓰레드가 이 자원(변수) 특정한 값으로 수정하는 기능이 있다면 동시에 접근하는 이유로 인하여 이 자원의 값이 제대로 된 값을 유지하지 못하는 경우가 있을 수 있다. 1122 | 1123 | 이와 같이 멀티스레드 환경에서 발생하는 문제를 해결하기 위한 일련의 작업을 스레드 동기화(Thread Synchronization)라 부른다. 스레드 동기화 방법에 대해서는 세마포어(Semaphore), 뮤텍스(Mutex) 등이 있다. 1124 | 1125 | ### Thread Synchronization in Java 1126 | 1127 | 자바에서는 이러한 임계영역의 처리를 위하여 synchronized, Semaphore 키워드를 제공하며 임계영역의 처리를 수행 1128 | 1129 | synchronized는 Mutex와 동일한 기능을, Semaphore는 말 그대로 세마포어의 기능을 수행한다. 1130 | 1131 | ```Java 1132 | 1133 | // synchronized 사용법 1134 | public synchronized void test 1135 | { 1136 | // 임계구역 작업 1137 | } 1138 | public void test 1139 | { 1140 | // 일반 작업 1141 | synchronized{ 1142 | // 임계구역 작업 1143 | } 1144 | } 1145 | 1146 | // Semaphore 사용법 1147 | public void test{ 1148 | 1149 | Semaphore semaphore = new Semaphore(maxThread); // 동시 접근 가능한 Thread 개수 1150 | semaphore.acquire(); // Thread 가 semaphore에게 시작을 알림 1151 | // 임계구역 작업 1152 | semaphore.release(); // Thread 가 semaphore에게 종료를 알림 1153 | } 1154 | ``` 1155 | 1156 | 1157 | 1158 | ## 📌 임계 구역 (Critical Section) 1159 | > 임계구역은 개념적 크리티컬 섹션과 기능적 크리티컬 섹션 두 가지 의미로 사용될 수 있지만, 자바에서는 개념적 크리티컬 섹션의 의미만을 사용 1160 | 1161 |

개념적 크리티컬 섹션

1162 | 1163 | - 여러 프로세스(스레드)가 데이터를 공유하며 수행될 때, 각 **프로세스(스레드)에서 공유 데이터를 접근하는 프로그램 코드 부분** 1164 | 1165 | 1166 | 1167 |

기능적 크리티컬 섹션

1168 | 1169 | - 동기화 목적을 위해 사용되는 배타적 제어를 하기 위한 구조(API) 1170 | - Windows 객체 중 하나이며, 프로그램에서 CRITICAL_SECTION 타입 변수를 통해 사용 1171 | - **자바에서는 사용하지 않음** 1172 | 1173 | 1174 | ## 📌 세마포어(Semaphore) 1175 | ![image](https://user-images.githubusercontent.com/55073084/134778576-66d21fac-04b1-4337-9646-d28e57b8ab98.png) 1176 | 1177 | - **Signaling 메커니즘** 을 통해 자원에 대한 접근을 동기화하는 기술 1178 | - 임계구역에 동시에 접근 가능한 스레드의 개수는 1개 이상이다. 1179 | - Signaling 메커니즘으로 락을 걸지 않은 스레드도 Signal을 통해 락을 해제할 수 있다. (wait 함수를 호출한 스레드만이 signal 함수를 호출할 수 있는 Mutex와의 차이점) 1180 | - Spin-Lock 방식과 Block & Wakeup의 2가지 방식의 사용법이 존재한다. (Spin-Up 방식은 CPU를 계속 점유하기 때문에 busy-wating이 발생한다는 단점이 있다.) 1181 | 1182 | ### 세마포어의 동작 원리 1183 | P (Wait) : 임계 구역에 들어가는 동작 (프로세스 진입 여부를 자원의 개수 S 를 통해 결정) 1184 | 1185 | V (Signal) : 임계 구역에서 나오는 동작 (자원 반납 알림, 대기 중인 프로세스를 깨우는 신호) 1186 | 1187 |

기본 동작

1188 | 1189 | ```C++ 1190 | wait(S); 1191 | // --- 임계 구역 --- 1192 | signal(S); 1193 | ``` 1194 | 1195 |

Spin-Lock(busy-waiting)

1196 | 1197 | ```C++ 1198 | wait(S) { 1199 | while (S <= 0); // 자원이 없다면 while 루프를 돌며 대기를 함. 1200 | 1201 | S--; // 자원을 획득함. 1202 | } 1203 | 1204 | signal(S) { 1205 | S++; // 자원을 해제함. 1206 | } 1207 | ``` 1208 | 1209 |

Block & Wakeup

1210 | 1211 | ```C++ 1212 | wait(semaphore *S) { 1213 | S->value--; 1214 | if (S->value < 0 ) { // 자원이 없다면 1215 | add this process to S->list; // 프로세스를 큐에 넣고 1216 | block(); // block 시킴 1217 | } 1218 | } 1219 | 1220 | signal(semaphore *S) { 1221 | S->value++; 1222 | if (S->value <= 0) { // 자원이 0이하라면 block중인 프로세스가 있다는 의미임. 1223 | remove a process P from S->list; // 대기하고 있는 프로세스를 가져옴. 1224 | wakeup(P); // 가져온 프로세스를 깨움. 1225 | } 1226 | } 1227 | ``` 1228 | 1229 | 1230 | ## 📌 뮤텍스(Mutex) 1231 | ![image](https://user-images.githubusercontent.com/55073084/134778802-9a3b5beb-e4eb-46b3-a10f-fa023480b6aa.png) 1232 | 1233 | - **Locking 메커니즘** 을 통해 자원에 대한 접근을 동기화하는 **상호배제 기술** 1234 | - Locking 메커니즘으로 오직 하나의 스레드만이 동일한 시점에 뮤텍스를 얻어 임계 영역에 들어갈 수 있다. 1235 | - Lock : 임계 구역의 사용 권한을 얻음 (만약 다른 스레드가 임계 구역 수행중이면 종료시까지 대기) 1236 | - unlock : 현재 임계 구역을 모두 사용했음을 알림 (대기중인 다른 스레드가 임계구역에 진입할수 있음) 1237 | - Lock을 건 스레드만이 임계 영역에서 나갈 때 뮤텍스를 해제할 수 있다. 1238 | - 뮤텍스는 상태가 1, 0 밖에 존재하지 않고, 바이너리 세마포어(Binary Semaphore)라고도 불림 1239 | 1240 | ### 뮤텍스 알고리즘 1241 | 1242 |

1. 데커 알고리즘 (Dekker's Algorithm)

1243 | 1244 | > 프로세스 두 개 일 때 상호 배제를 보장하는 알고리즘 1245 | > flag와 turn 변수를 통해 임계 구역에 들어갈 프로세스/스레드를 결정하는 방식 1246 | - flag : 프로세스 중 누가 임계영역에 진입할 것인지 나타내는 변수 1247 | - turn : 누가 임계구역에 들어갈 차례인지 나타내는 변수 1248 | 1249 | ```C++ 1250 | while(true) { 1251 | flag[i] = true; // 프로세스 i가 임계 구역 진입 시도 1252 | 1253 | while(flag[j]) { // 프로세스 j가 현재 임계 구역에 있는지 확인 1254 | if(turn == j) { // j가 임계 구역 사용 중이면 1255 | flag[i] = false; // 프로세스 i 진입 취소 1256 | 1257 | while(turn == j); // turn이 j에서 변경될 때까지 대기 1258 | 1259 | flag[i] = true; // j turn이 끝나면 다시 진입 시도 1260 | } 1261 | } 1262 | } 1263 | 1264 | // ------- 임계 구역 --------- 1265 | 1266 | turn = j; // 임계 구역 사용 끝나면 turn을 넘김 1267 | flag[i] = false; // flag 값을 false로 바꿔 임계 구역 사용 완료를 알림 1268 | 1269 | ``` 1270 | 1271 |

2. 피터슨 알고리즘 (Peterson's Algorithm)

1272 | 1273 | > 프로세스 두 개 일 때 상호 배제를 보장하는 알고리즘 1274 | > 데커와 유사하지만, 상대방 프로세스/스레드에게 진입 기회를 양보하는 것에 차이가 있음 1275 | 1276 | ```C++ 1277 | while(true) { 1278 | flag[i] = true; // 프로세스 i가 임계 구역 진입 시도 1279 | turn = j; // 다른 프로세스에게 진입 기회 양보 1280 | while(flag[j] && turn == j) { // 다른 프로세스가 진입 시도하면 대기 1281 | } 1282 | } 1283 | 1284 | // ------- 임계 구역 --------- 1285 | 1286 | flag[i] = false; // flag 값을 false로 바꿔 임계 구역 사용 완료를 알림 1287 | 1288 | ``` 1289 | 1290 |

3. 램퍼드의 제과점 알고리즘 (Lamport's bakery algorithm)

1291 | 1292 | > 여러 프로세스/스레드에 대한 처리가 가능한 알고리즘. 1293 | > 프로세스에게 고유한 번호를 부여하고, 번호를 기준으로 우선순위를 정하여 우선순위가 높은 프로세스가 먼저 임계 구역에 진입하도록 구현 (번호가 낮을수록 우선순위가 높음) 1294 | 1295 | ```C++ 1296 | while(true) { 1297 | 1298 | isReady[i] = true; // 번호표 받을 준비 1299 | number[i] = max(number[0~n-1]) + 1; // 현재 실행 중인 프로세스 중에 가장 큰 번호 배정 1300 | isReady[i] = false; // 번호표 수령 완료 1301 | 1302 | for(j = 0; j < n; j++) { // 모든 프로세스 번호표 비교 1303 | while(isReady[j]); // 비교 프로세스가 번호표 받을 때까지 대기 1304 | while(number[j] && number[j] < number[i] && j < i); 1305 | 1306 | // 프로세스 j가 번호표 가지고 있어야 함 1307 | // 프로세스 j의 번호표 < 프로세스 i의 번호표 1308 | } 1309 | } 1310 | 1311 | // ------- 임계 구역 --------- 1312 | 1313 | number[i] = 0; // 임계 구역 사용 종료 1314 | 1315 | ``` 1316 |
1317 | 1318 | 1319 | 1320 | # 주 메모리와 가상 메모리 1321 | 1322 | ## 주 메모리(Main Memory) 1323 | 1324 | 메모리는 주소가 할당된 일련의 워드 또는 바이트로 구성됩니다. CPU는 메모리로부터 다음 수행할 명령어를 가져오기때문에 메모리를 관리하는 것은 매우 중요한 일입니다. 1325 | 1326 | ## 주 메모리와 관련된 배경 지식 1327 | 1328 | ### 기본 하드웨어 1329 | 1330 | - 주 메모리 및 레지스터 : CPU가 접근할 수 있는 유일한 저장장치입니다. 따라서 모든 명령어와 자료들은 CPU가 직접 접근할 수 있는 주 메모리와 레지스터에 존재해야 합니다. 1331 | - 베이스(base) 레지스터 : 각 프로세스는 독립된 메모리 공간을 갖습니다. 따라서 특정 메모리 공간에는 특정 프로세스만 접근할 수 있도록 합법적인 메모리 주소 영역을 설정해야 합니다. 가장 작은 합법적인 물리 메모리 주소 값을 저장하는 것이 베이스 레지스터입니다. 1332 | - 상한(limit) 레지스터 : 주어진 영역의 크기를 저장합니다 1333 | 1334 | >- 만약 베이스 레지스터 값이 300040 이고 상한 레지스터 값이 120900이라면 프로그램은 300040에서 420940까지의 모든 주소에 접근할 수 있습니다. 1335 | 1336 |
1337 | 1338 | ### 주소의 할당(Address Binding) 1339 | 1340 | 이진 실행 파일 형태의 **프로그램**은 **디스크**에 존재하고 있다가 프로그램이 실행되면 **주 메모리**로 올라와 **프로세스**가 됩니다. 프로세스는 실행 동안 디스크와 주 메모리 사이를 이동할 수 있는데 이를 위해 프로세스가 사용했던 기억 공간(주소) 할당이 필요합니다. 1341 | 1342 | 메모리 주소 공간에서 명령어와 자료의 할당 시점은 다음과 같이 분류됩니다. 1343 | 1344 | #### 컴파일 시간 할당(Compile Time Binding) 1345 | 1346 | 컴파일 시 프로세스가 물리 메모리 내 진입할 위치를 알 수 있습니다. 즉 컴파일 시 바인딩 된 주소는 절대적인 주소이며, 논리적인 주소와 물리적인 주소가 같습니다. 따라서 이후 물리 메모리 위치를 변경해야할 경우 컴파일을 다시 해야합니다. 1347 | 1348 | #### 적재 시간 할당(Load Time Binding) 1349 | 1350 | 컴파일 시 물리 메모리 위치를 알 수 없다면 컴파일러는 일단 이진 코드를 재배치 가능 코드로 만들고, 심볼과 번지수 할당은 프로그램이 주 메모리에 적재되는 시간에 이루어집니다. 따라서 프로그램 내부에서 사용하는 논리적인 주소와 실제 주 메모리 상의 물리적인 주소는 다릅니다. 이후 물리 메모리 위치를 변경해야할 경우 재적재를 해야합니다. 1351 | 1352 | #### 실행 시간 할당(Execution Time Binding/RunTime Binding) 1353 | 1354 | 프로세스가 실행하는 중간에도 메모리 내의 한 세그먼트에서 다른 세그먼트로 물리 메모리 주소가 이동할 수 있는 경우를 말합니다. 이를 위해서는 하드웨어적인 지원(MMU, Memory Management Unit)과 주소 매핑 테이블이 필요합니다. 1355 | 1356 |
1357 | 1358 | ### 논리 주소 공간과 물리 주소 공간 1359 | 1360 | CPU가 생성하는 주소를 **논리 주소**(Logical Address), 메모리가 취급하는 주소(메모리 주소 레지스터에 주어지는 주소)를 **물리 주소**(Physical Address)라고 합니다. 1361 | 1362 | 컴파일 시간 바인딩은 논리 주소와 물리 주소가 같지만, 실행 시간 바인딩은 다릅니다. 흔히 정적 바인딩과 동적 바인딩이라고하는 개념도 이것을 말하는 것이죠. 따라서 프로그램 실행 중에는 가상 주소(논리 주소)를 물리 주소로 바꿔줘야 하고, 이 변환을 위한 기법에는 재배치(relocation) 레지스터가 있습니다. 1363 | 1364 | 사용자 프로그램의 경우 실제적인 물리 주소를 절대 알 수 없습니다. 사용자 프로그램은 오직 논리 주소를 사용한 것이고, 메모리 하드웨어 상 주소는 논리 주소를 물리 주소로 바꾼 것입니다. 1365 | 1366 |
1367 | 1368 | ### 동적 적재(Dynamic Loading) 1369 | 1370 | 프로세스는 실행되기 전 모든 자료가 미리 메모리에 올라가 있어야하는데, 만약 메모리 크기가 프로세스 크기보다 작다면 이는 불가능합니다. 이를 해결하기 위한 것이 동적 적재입니다. 1371 | 1372 | 동적 적재는 각 루틴을 재배치 가능 상태로 만들어 디스크에서 대기시킨 뒤, 메모리에 올라가 있는 주 프로그램이 해당 루틴을 필요로 해 호출한 시기에 재배치 가능 연결 적재기(relocatable linking loader)를 이용해 주 메모리로 올립니다. 1373 | 1374 | 따라서 사용되지 않는 루틴은 결코 미리 적재되지 않기때문에 메모리를 절약할 수 있습니다. 1375 | 1376 |
1377 | 1378 | ### 동적 연결과 공유 라이브러리(Dynamic Linking & Shared Library) 1379 | 1380 | 시스템 라이브러리를 실제 해당 라이브러리를 실행할 때에 동적으로 연결하는 것을 말합니다. 1381 | 1382 | 프로그램 실행 시 시스템 라이브러리를 부르면 스텁(stub)이라는 작은 코드 조각이 생깁니다. 이 스텁을 이용해 필요로 하는 라이브러리가 디스크와 메모리 중 어디에 존재하는지 번지수를 찾고, 다음번에는 기억했던 번지수를 이용해 쉽게 라이브러리 루틴을 수행할 수 있습니다. 1383 | 1384 |
1385 | 1386 | ## 주 메모리 할당 기법 1387 | 1388 | ### 스와핑(Swapping) 1389 | 1390 | 프로세스는 실행 시 주 메모리에 올라와 있어야 하지만 라운드 로빈과 같은 CPU 스케줄링 시 잠시 보조 메모리로 보내졌다가 돌아오게될 수도 있습니다. 이렇게 프로세스를 주 메모리와 예비 저장 장치 사이에서 이동시키는 것을 스와핑이라고 합니다. 보조 메모리는 주로 디스크를 사용합니다. 1391 | 1392 | 주 메모리에서 보조 메모리로 이동하는 것을 스왑 아웃(swap out), 보조 메모리에서 주 메모리로 이동하는 것을 스왑 인(swap in)이라고 합니다. 1393 | 1394 | 어셈블리 혹은 적재 시간 바인딩 프로세스의 경우 동일한 주소로 스왑되어야 하지만 실행 시간 바인딩 프로세스의 경우 빈 메모리의 어떤 공간으로도 스왑될 수 있습니다. 1395 | 1396 | 스와핑은 문맥 교환 시간(context-switch time) 상당히 걸리므로, 프로세스를 라운드 로빈 스케줄링 기법으로 관리한다면 시간 할당량은 문맥 교환 시간보다 커야겠죠. 1397 | 1398 | 스왑을 할 프로세스는 반드시 유휴 상태여야 합니다. 만약 입/출력 장치와 신호를 주고받던 프로세스를 스왑하게 된다면 잘못된 입/출력 내용이 저장되거나 다른 프로세스에게 저장될 수도 있습니다. 1399 | 1400 | 일반적으로 디스크 내의 스왑공간은 파일 시스템과 별도로 할당되도록 하여 스왑 시간을 단축할 수 있습니다. 1401 | 1402 |
1403 | 1404 | ### 연속 메모리 할당(Contiguous allocation) 1405 | 1406 | 초기 컴퓨터 시스템의 경우 한 컴퓨터는 한 사용자만이 사용했고, 또한 많은 프로그램을 동시에 실행시키지 않았습니다. 따라서 한 프로세스가 실행되기 위해 메모리 공간을 요구할 경우 메모리 상의 연속된 덩어리 공간을 할당해주는 연속 메모리 할당 방식을 이용했습니다. 프로세스는 메모리 덩어리의 시작 주소를 통해 할당받은 메모리에 접근할 수 있으며, 각종 변수와 함수들을 바인딩하여 사용하였습니다. 1407 | 1408 | #### 단일 사용자 할당 1409 | 메모리는 일반적으로 두 부분으로 나눌 수 있습니다. 하나는 메모리에 상주하는 운영체제를 위한 것이고, 나머지는 사용자 프로세스를 위한 것입니다. 1410 | 1411 | 위에서 언급한 것과 같이 초기 컴퓨터 시스템은 단일 사용자에 의해서만 사용되었으므로 사용자 프로세스를 위한 공간을 나누어 사용할 필요가 없었습니다. 따라서 운영체제를 위한 메모리는 주로 인터럽트 벡터가 위치한 0번지 근처(하위 메모리)에 위치시키고, 사용자 프로세스를 위한 메모리는 나머지 공간을 연속적으로 사용했습니다. 1412 | 1413 | #### 다중 분할 할당 1414 | 1415 | 점점 실행되는 사용자 프로세스가 많아지며 사용자 프로세스를 위한 메모리 영역은 다시 여러 프로세스를 위해 다중으로 분할되어 할당되어야 하는 문제가 떠올랐습니다. 이렇게 사용자 프로세스를 위한 메모리 공간을 다중으로 할당하는 것을 다중 분할 할당이라고 합니다. 이를 위한 기법으로는 **고정 분할 할당**(Multiple Contiguous Fixed Partition Aloocation, MFT)과 **가변 분할 할당**(Multiple Contiguous Variable Partition Aloocation, MVT) 기법이 있습니다. 1416 | 1417 | 1. 고정 분할 할당 기법(정적 분할(Static Allocation) 기법) 1418 | - 메모리를 똑같은 고정된 크기로 분할하여 각 분할을 하나의 프로세스에게만 할당하는 방법 1419 | - 각 분할 개수는 다중 프로그래밍 정도 1420 | - 한 분할이 비게 되면 입력 큐의 다른 프로세스가 해당 분할을 차지 1421 | - 주로 초기 운영체제에 사용됨 1422 | 1423 | 2. 가변 분할 할당 기법(동적 분할(Dynamic Allocation) 기법) 1424 | - 미리 주 메모리를 분할하는 것이 아니라, 적재 시 필요한 만큼 크기로 영역을 분할하는 방법 1425 | - 주 메모리의 어떤 부분이 얼마나 사용되고 있는지 파악하는 테이블을 관리 1426 | - 메모리 내에 여러 크기 공간이 산재되어 있으므로 이 공간을 쪼개어 사용하거나 인근 공간을 합쳐 큰 공간으로 만드는 등의 과정을 고려해야 함 1427 | 1428 | #### 동적 공간 할당 문제 1429 | 1430 | 위의 가변 분할 할당 기법에서는 프로세스의 메모리 요구량에 따라 산재되어있는 주 메모리를 쪼개어 사용할 지, 아니면 합쳐 사용할 지 결정해야 합니다. 즉, 일련의 메모리 공간과 프로세스 리스트를 어떻게 할당할 지 결정하는 문제를 동적 공간 할당 문제라고 합니다. 1431 | 1432 | 동적 공간 할당 문제를 해결하는 방법에는 다음과 같은 세 가지 해결책이 존재합니다. 1433 | 1434 | 1. 최초 적합 1435 | - 첫번쨰 사용 가능한 공간을 할당 1436 | - 메모리 검색 시 할당이 가능한 충분히 큰 자유 공간을 찾으면 검색 종료 1437 | 2. 최적 적합 1438 | - 사용 가능한 공간 중 *가장 작은 것* 선택 1439 | - 리스트가 오름차순으로 정렬되어 있어야 함 1440 | - 아주 작은 나머지 공간 발견 1441 | 3. 최악 적합 1442 | - 사용 가능한 공간 중 *가장 큰 것* 선택 1443 | - 역시 리스트가 정렬되어 있어야 함 1444 | 1445 | 일반적으로는 최초 적합과 최적 적합이 최악 적합에 비해 시간, 메모리 효율이 뛰어나다고 알려져 있습니다. 1446 | 1447 | #### 단편화(Fragmentation) 1448 | 1449 | 메모리 할당 시 메모리 공간 중 일부는 사용자에 의해 사용될 수 없는 빈 공간이 존재하는 문제가 발생할 수 있습니다. 이런 *빈 공간*을 단편화라고 합니다. 1450 | 1451 | 단편화는 전체 주 메모리 중 듬성 듬성 비어있는 공간인 **외부 단편화**와, 사용자에게 할당된 주 메모리 공간 중 넉넉하게 할당되어 사용되지 않는 공간인 **내부 단편화**로 나눌 수 있습니다. 1452 | 1453 | 1. 외부 단편화 1454 | - 주 메모리 중 프로세스에게 할당되지 않은 프로세스와 프로세스 사이 틈새의 작은 자유 공간 1455 | - 이 자유 공간을 합쳐 하나의 큰 자유 공간을 만든다면 더 많은 프로세스를 할당할 수 있음 1456 | - 단편화의 크기와 메모리의 빈 공간 위치에 따라 최초 적합과 최적 적합 기법을 적용할 수 있음 1457 | - 또한 **압축**을 통해 메모리의 모든 내용을 한 부분으로 몰고 나머지 자유 공간을 여유롭게 사용할 수도 있음 1458 | - 하지만 이를 위해서는 프로세스 내의 모든 주소들이 동적으로 재배치되어야 하고, 실행시간에 동적으로 바인딩 되는 경우에만 적용 가능함 1459 | 2. 내부 단편화 1460 | - 프로세스가 요구하는 공간보다 할당된 공간이 약간 더 클 때 생기는 자유 공간 1461 | - 프로세스가 요구하는 공간을 정확히 할당해주는 것보다 약간 더 크게 할당해주고 공간을 낭비하는 것이 어떤 면에서는 비용적으로 더 효율적일 수 있음 1462 | 1463 |
1464 | 1465 | ### 불연속 메모리 할당(Contiguous allocation) 1466 | 1467 | 위의 연속 메모리 할당에서 발생하는 단편화 문제를 해결하기 위해 한 프로세스를 위한 메모리를 메모리 상 여러 영역으로 분산하여 할당해주는 기법이 등장합니다. 다음으로 불연속 메모리 할당을 가능하게하는 페이징과 세그멘테이션 기법에 대해 알아봅시다. 1468 | 1469 | #### 페이징 1470 | 1471 | 주 메모리와 같이 디스크(보조 메모리) 역시 논리 주소의 할당 문제, 단편화 문제가 발생합니다. 하지만 디스크는 주 메모리보다 속도가 느리기때문에 압축과 같은 방법으로 주소 할당 문제를 해결하기 어렵습니다. 이를 해결하기 위한 방법이 바로 페이징입니다. 1472 | 1473 | 페이징은 논리 주소 공간이 한 연속적인 공간에 모여있어야 한다는 제약을 없앴습니다. 따라서 프로세스를 주 메모리에서 디스크로 넘길 때 프로세스의 크기에 맞는 연속된 공간을 찾지 않아도 됩니다. 1474 | 1475 | ##### 페이징 원리 1476 | 1477 | 물리 메모리는 프레임(frame), 논리 메모리는 페이지(page)라 불리는 동일한 크기의 여러 블록으로 나누어져 있습니다. 1478 | 1479 | CPU에서 나오는 모든 주소는 **페이지 번호**(p)와 **페이지 변위**(d: offset)로 나뉩니다. 페이지 테이블은 *주 메모리 내의 페이지 점유 주소*를 표현하고 있는데, 페이지 번호로 이 테이블에 엑세스하여 페이지 주소를 파악할 수 있습니다. 페이지 주소에 페이지 변위를 더한 것이 물리주소가 됩니다. 1480 | 1481 | ![paging](./img/paging.png) 1482 | 1483 | 페이징 역시 동적 재배치의 한 형태입니다. 페이징을 사용할 경우 모든 유휴 상태 프레임이 프로세스에 할당될 수 있으므로 외부 단편화는 발생하지 않습니다. 하지만 내부 단편화를 피할 수는 없습니다. 공간 할당이 늘 프레임의 정수 배로 할당되기 때문입니다. 이를 고려했을 때는 작은 페이지 크기가 바람직하지만, 이에 반비례하여 페이지 테이블의 크기가 커지는 문제가 발생하므로 디스크 입장에서는 페이지 크기가 클 수록 효율적입니다. 1484 | 1485 | 프로세스가 실행을 위해 큐에 도착하면 몇 개의 페이지를 필요로 하는지 확인합니다. 한 페이지는 한 개의 프레임을 필요로 하므로, 프로세스가 n개의 페이지를 요구하면 메모리 내에 n개의 프레임이 존재해야 합니다. 프로세스는 페이지가 할당된 프레임 중 하나에 적재되고 이 프레임 번호는 페이지 테이블에 기록되는 방식으로 할당합니다. 1486 | 1487 | 페이징에서 중요한 것은 일반적인 사용자의 인식과 달리, 논리 주소와 실제 물리 주소에는 차이가 존재한다는 것입니다. 언뜻 보면 메모리는 하나의 연속적인 공간이고 하나의 프로그램이 메모리를 점유하는 것처럼 보이지만, 실제로는 다양한 프로그램들이 메모리의 여러 곳에 프레임 단위로 분산되어 있습니다. 따라서 운영체제는 논리 주소를 매핑하여 물리 주소로 스스로 연결하고, 각 프로세스는 페이지 테이블 내의 주소만 접근하므로 자신의 메모리가 아닌 다른 프로세스의 메모리에 접근할 수 없습니다. 페이지 테이블과 같이 운영체제가 물리 메모리 할당에 대한 파악을하기 위한 목적으로 프레임 테이블을 구성하고 있습니다. 1488 | 1489 |
1490 | 1491 | ##### 페이지 테이블 저장 방법 1492 | 1493 | - 레지스터 집합 구현 : 효율적인 페이징 주소 변환. 단, 페이지 테이블이 작을 경우 적합. 1494 | - 페이지 테이블 기준 레지스터(PTBR) : 주 메모리에 저장한 페이지 테이블을 가리키도록 하는 레지스터. 페이지 테이블 교환 시 레지스터만 변경하면 되므로 문맥 교환 시간 단축 가능. 단, 메모리 접근 시간이 많이 걸림. 1495 | 1496 |
1497 | 1498 | ##### 페이지 테이블에 의한 메모리 보호 1499 | 1500 | 페이지 테이블에는 메모리를 보호하기 위한 보호 비트가 구현되어 있습니다. 보호 비트는 해당 페이지가 읽기 전용 페이지인지, 아니면 읽기 쓰기가 가능한 페이지인지를 정의하고 있습니다. 따라서 부적잘한 접근을 막을 수 있습니다. 1501 | 1502 | 또한 프로세스의 합법적인 페이지인지 여부를 나타내는 유효/무효(valid/invalid) 비트가 존재하여 메모리를 보호합니다. 1503 | 1504 |
1505 | 1506 | ##### 공유 페이지 1507 | 1508 | 페이지의 큰 장점 중 하나는 코드를 쉽게 공유할 수 있다는 것입니다. 재진입 가능 코드로 구현한다면 여러 프로세스에 의해 접근될 수 있습니다. 1509 | 1510 | 공유 페이지는 쓰레드 주소 공간 공유와 유사하며, 프로세스 간 상호 통신의 방법으로 공유됩니다. 1511 | 1512 |
1513 | 1514 | ##### 페이지 테이블의 구조 1515 | 1516 | 1. 계층적 페이징 1517 | 1518 |

1519 | 1520 | - 페이지 테이블 자체가 다시 페이지화되는 것(2단계 페이징 기법) 1521 | - 주소 변환이 바깥 페이지 테이블에서 시작하여 안쪽으로 들어오는 형식(포워드 매핑 페이지 테이블) 1522 | - 페이지 테이블을 나눔으로써 운영체제는 프로세스가 각 분할들을 실제로 필요로 할 때까지 사용하지 않은 채 남겨둘 수 있음 1523 | - 단, 논리 주소 사상 시 너무 많은 메모리를 접근하게 되므로 비현실적인 상황에 도달할 수 있음 1524 | 1525 | 2. 해시형 페이지 테이블 1526 | 1527 | - 해시 값이 가상 페이지 번호가 됨 1528 | - 가상 주소 공간으로부터 페이지 번호를 받으면 해싱 시도 1529 | - 해시형 페이지 테이블에서 연결 리스트를 따라가며 첫번째 원소와 가상 페이지 번호를 비교. 일치할 경우 페이지 프레임 번호를 가져와 물리 주소를 얻고, 아닐 경우 연결리스트 다음 원소로 탐색 1530 | - 클러스터형 페이지 테이블은 해시형에서 조금 발전하여 각 항목이 여러개 페이지를 가리키도록 함 1531 | - 클러스터형은 메모리 접근이 불연속적이고 전 주소공간으로 넓게 퍼져 나오는 경우에 유리 1532 | 1533 | 3. 역 페이지 테이블 1534 | 1535 | - 메모리 프레임마다 한 항목씩을 할당(페이지마다 하나의 항목을 가지는 것을 반대로 함) 1536 | - 각 항목 별로 해당 프레임에 올라와 있은 페이지 주소, 페이지를 소유하고 있는 프로세스의 ID가 표시되어 있음 1537 | - 따라서 시스템에는 단 하나의 페이지 테이블이 존재하고, 테이블 내 각 항목은 메모리 프레임을 하나씩 가리키게 됨 1538 | - 논리 페이지마다 항목을 가지는 대신 물리 프레임에 대응되는 항목만 테이블에 저장하므로 메모리 공간을 절약할 수 있음 1539 | - 단, 반대로 주소 변환 비용이 많이 듦. 테이블에서 가상 페이지 주소를 탐색하기 위해서는 테이블 전체를 탐색해야 함. 1540 | - 하나의 물리영역에 여러 개의 가상 주소를 매핑할 수 없으므로 메모리 공유가 어려움 1541 | 1542 |
1543 | 1544 | #### 세그먼테이션(Segmentation) 1545 | 1546 | 앞서 언급했듯이 사용자의 메모리 관점과 실제 물리 메모리 관점은 다릅니다. 사용자(프로그래머)는 종종 프로그램을 작성하면서 함수나 모듈, 자료구조에 대해 메모리의 몇번째 주소로부터 몇 개의 바이트를 이용한다는 식으로 생각합니다. 이러한 사용자 관점에서의 메모리 관리를 가능하게 하는 메모리 관리 기법을 **세그먼테이션**이라고 합니다. 1547 | 1548 | ##### 구현 1549 | 1550 | 세그먼테이션에서는 논리 주소 공간을 세그먼트 집합으로 정의합니다. 각 세그먼트는 이름과 길이를 가집니다. 단, 세그먼트는 구현을 쉽게 하기 위해 내부에서 번호로 불립니다. 따라서 논리 주소는 (segment number, offset(변위))로 구성됩니다. 1551 | 1552 | > 예를 들어 봅시다. 1553 | > C언어 프로그램을 컴파일할 경우 컴파일러는 자동적으로 다음과 같은 세그먼트들을 만들어낼 것입니다. 1554 | >- 코드 1555 | >- 전역변수 1556 | >- 메모리 할당을 위한 힙(heap) 1557 | >- 각 쓰레드를 위한 스택(stack) 1558 | >- 표준 C 라이브러리 1559 | > 이때 적재기는 위의 세그먼트들을 받아 각각 번호를 매겨줍니다. 1560 | 1561 | 사용자가 정의한 각 세그먼트의 2차원 주소(ex. (3번째 세그먼트, 18번째 바이트))는 실제 메모리 상에서 바이트의 1차원 구조로 구성되어 있으므로 이 둘을 올바르게 매핑하기 위해 **세그먼트 테이블**이 존재합니다. 1562 | 1563 | 세그먼트는 세그먼트 이름에 해당하는 **세그먼트 번호**와 세그먼트 내에서 몇 번째 인지 위치에 해당하는 **세그먼트 변위**(offset)로 표현됩니다. 이를 물리 주소로 매핑하기 위해 세그먼트 테이블은 세그먼트의 시작 주소를 나타내는 **세그먼트의 기준**(base)과 세그먼트의 길이를 나타내는 **세그먼트 한계**(limit)을 가지고 있습니다. 1564 | 1565 | 세그먼트 번호를 통해 세그먼트 테이블에 색인을할 수 있는데, 이때 변위가 0과 세그먼트 크기 사이의 값이 아니라면 오류로 인식되어 트랩(trap)이 발생할 수 있습니다. 1566 | 1567 |
1568 | 1569 | --- 1570 | 1571 | ## 가상 메모리(Virtual Momory) 1572 | 1573 | 현재 실행중인 코드는 반드시 물리 메모리에 존재해야한다고 생각할 수 있습니다. 하지만 다음과 같은 상황을 생각해봅시다. 1574 | 1575 | >- 프로그램에서 가끔 발생하는 예외를 처리하기 위한 코드 1576 | >- 크기가 제한된 형태인 배열(array)을 이용하기 위해 필요한 크기보다 훨씬 큰 크기로 선언한 경우 1577 | >- 정말 가끔 사용하는 옵션 1578 | >- 위와 같이 당장 필요하지 않은 코드들 1579 | 1580 | 위와 같은 경우를 고려했을 때 모든 코드를 늘 물리 메모리에 올려놓을 필요는 없으며, 그렇게 한다고 할지라도 물리 메모리 크기는 제한적이기 때문에 불가능할 수도 있습니다. 1581 | 1582 | 이를 해결하기 위해 가상 메모리를 사용합니다. **가상 메모리**는 실제의 물리 메모리 개념과 사용자의 논리 메모리 개념을 분리한 것입니다. 프로그램 중 당장 필요한 일부만을 물리 메모리에 올려놓고 실행하는 것이죠. 1583 | 1584 | ### 이점 1585 | 1586 | - 프로그램은 물리 메모리 크기에 제약받지 않을 수 있습니다. 프로그래머들은 매우 큰 *가상 주소 공간*을 가정하고 프로그래밍을 할 수 있습니다. 1587 | - 각 프로그램의 코드 중 일부만이 메모리를 차지하므로 더 많은 프로그램이 동시에 수행될 수 있습니다. 이는 응답시간의 감소와 CPU 이용률 및 처리율을 향상시킵니다. 1588 | - 프로그램을 메모리에 올리고 스왑할 때 발생하는 입/출력 비용이 감소합니다 1589 | - 페이지 공유를 통해 파일이나 메모리가 둘 이상의 프로세스들에 의해 공유되는 것이 가능합니다. 1590 | 1591 | ![Virtual-Memory](./img/virtual-memory.png) 1592 | 1593 |
1594 | 1595 | ## 요구 페이징 1596 | 1597 | 일반적인 가상 메모리는 보통 요구 페이징으로 구현합니다. **요구 페이징**은 프로그램 실행 시 모든 부분을 메모리에 적재하는 것이 아니라, 실행 과정에서 페이지를 요구할 때마다, 즉 페이지들이 필요해질 때마다 적재하는 전략입니다. 1598 | 1599 | 요구 페이징은 스와핑과 개념이 유사합니다. 스와핑에서는 보조 메모리의 프로세스를 실행하고 싶을 때에 주 메모리로 읽어옵니다(swap in). 이와 같이 프로세스 내 페이지를 관리하는 페이저(pager)는 프로세스가 스왑 아웃(swap out)되기 전에 실제로 사용될 페이지가 어떤 것일지 추측하고, 이후에는 프로세스 전체를 스왑인 하는 대신 실제 필요한 페이지만 메모리로 읽어옵니다. 1600 | 1601 | 이를 위해서는 하드웨어 적인 기술이 필요한데, 유효/무효 비트를 사용하여 페이지가 메모리에 존재할 경우 유효(valid)하다고 표시하고, 페이지가 가상 주소 공간에 정의되지 않았거나 디스크에 존재할 경우 무효(invalid)하다고 표시하거나 페이지가 현재 저장된 디스크 주소를 기록합니다. 1602 | 1603 | ### 순수 요구 페이징 1604 | 1605 | 특정 페이지가 필요해 실제로 참조하기 전에는 절대 그 페이지를 메모리로 적재하지 않는 방법을 말합니다. 이를 통해 전체 프로세스가 주 메모리에 올라와있지 않아도 프로세스를 실행할 수 있습니다. 1606 | 1607 | 메커니즘은 다음과 같습니다. 1608 | 1609 | 1. 실제로 참조하지 않는 페이지는 초기에 메모리에 올리지 않으므로 어떤 페이지도 메모리에 올라가 있지 않음 1610 | 2. 특정 페이지에 대한 참조가 발생 1611 | 3. 페이지 부재(page fault) 발생 1612 | 4. 운영체제는 내부 테이블을 통해 해당 페이지가 디스크 내부 어디에 위치했는지 파악 1613 | 5. 자유 프레임을 탐색하여 디스크로부터 해당 페이지를 읽어옴 1614 | 6. 페이지 테이블 내애 페이지에 변화가 생겼음을 표시 1615 | 7. 3에서 페이지 부재로 중지되었던 명령이 다시 실행됨 1616 | 1617 | 위에서 볼 수 있듯이 요구 페이징의 성능은 페이지 부재에 의해 좌우됩니다. 따라서 **페이지 부재율을 낮게 유지**하는 것이 중요하겠죠. 1618 | 1619 |
1620 | 1621 | ## 페이지 교체 1622 | 1623 | 요구 페이징에서 주요 관건은 페이지 교체와 프레임 할당 문제를 해결하는 것입니다. 디스크 입/출력 비용은 결코 만만하게 볼 수 없기때문이죠. 1624 | 1625 | 먼저 페이지 교체부터 봅시다. 실제 시스템이 보유한 페이지보다 더 많은 프로세스가 더 많은 페이지를 요구할 경우, 페이지 간 교체를 해야하는 문제가 발생합니다. 이렇게 희생될 페이지를 골라야 하는 순간에서 고려할 수 있는 페이지 교체 알고리즘에 대해 알아봅시다. 1626 | 1627 |
1628 | 1629 | ### FIFO 페이지 교체(First-In-First-Out) 1630 | 1631 | ![FIFO-page-replacement](./img/fifo-page-replace.png) 1632 | 1633 | - 메모리에 올라온 페이지 중 **가장 오래된 페이지**를 교체하는 방법 1634 | - 페이지가 올라온 시간을 기록하거나, 페이지가 올라온 순서대로 큐(queue)를 생성하여 관리 1635 | - 장점 : 가장 직관적이고 단순한 알고리즘 1636 | - 단점 : 1637 | - 성능이 좋지 않음(페이지 교체 직후 바로 해당 페이지를 필요로 하는 경우 등) 1638 | - 더 많은 프레임을 할당했음에도 불구하고 페이지 부재율이 높을 수 있는 Belady의 모순이 발생함 1639 | 1640 |
1641 | 1642 | ### 최적 페이지 교체(OPT, Optimal page replacement) 1643 | 1644 | ![OPT-page-replacement](./img/opt-page-replace.png) 1645 | 1646 | - 앞으로 가장 오랜 동안 **사용되지 않을** 페이지를 찾아 교체하는 방법 1647 | - 장점 : 가장 낮은 페이지 부재율을 보장하는 최적의 알고리즘 1648 | - 단점 : 실제 구현이 거의 불가능하므로(미래의 프로세스 참조를 예측하기란 쉽지 않음) 비교 연구 목적으로 사용됨 1649 | 1650 |
1651 | 1652 | ### LRU 페이지 교체(Least-Recently-Used) 1653 | 1654 | ![LRU-page-replacement](./img/lru-page-replace.png) 1655 | 1656 | - 가장 오랜 기간 동안 **사용되지 않은** 페이지를 교체하는 방법 1657 | - 최적 알고리즘의 근사 알고리즘으로 최근의 과거를 가까운 미래의 근사치로 생각함 1658 | - 각 페이지마다 마지막 사용 시간을 기록하여 구현 1659 | - 카운터(counter) : 각 페이지 별 사용 시간 필드와 카운터를 추가하여 메모리 접근 시마다 시간을 증가시킴. 페이지 테이블이 변경될 때마다 시간 값을 관리해야 함. 1660 | - 스택(stack) : 페이지가 참조될 때마다 페이지 번호를 스택 중간에서 빼내어 스택 top에 삽입. 스택의 꼭대기에는 항상 가장 최근에 사용된 페이지가, 스택 밑바닥에는 항상 가장 이전에 사용된 페이지가 위치함. 스택의 중간에서 꺼내고 다시 top으로 삽입하는 과정에서 오버헤드가 발생하긴 하지만 페이지 교체 시 페이지를 탐색할 필요 없이 top만 보면 됨. 1661 | - 장점 : OPT와 근사하게 좋은 성능을 보장 1662 | - 단점 : 카운터나 스택과 같은 구현을 위해 하드웨어 지원이 필요함 1663 | 1664 |
1665 | 1666 | ### LRU 근사 페이지 교체(LRU Approximation) 1667 | 1668 | 하드웨어의 지원을 필요로하는 LRU 페이지 교체 알고리즘의 한계를 극복하기 위한 알고리즘입니다. 주로 페이지 별 참조 비트를 설정하여 사용합니다. 1669 | 1670 | #### 부가적 참조 비트 알고리즘 1671 | 1672 | - 일정한 간격마타 참조 비트를 기록함으로써 페이지 사용 선후 관계를 기록 1673 | 1674 | #### 이차 기회 알고리즘(클럭 알고리즘) 1675 | 1676 | - FIFO 교체 알고리즘을 기반으로 함. 1677 | - 페이지를 순환 큐에 저장하고, 페이지가 선택될 때마다 참조 비트를 확인하여 값이 `0`인 경우에는 페이지를 교체하고 `1`인 경우에는 한번 더 기회를 줌 1678 | - 자주 사용되는 페이지의 경우 교체될 가능성이 낮음 1679 | 1680 |
1681 | 1682 | ### 계수 기반 페이지 교체(Counting-Based) 1683 | 1684 | #### LFU 알고리즘(Least-Frequently-Used) 1685 | 1686 | - 참조 횟수가 가장 적은 페이지를 교체하는 방법 1687 | - 장점 : 자주 사용되는 페이지는 참조 횟수가 크므로 교체가 적을 수 있음 1688 | - 단점 1689 | - 한 프로세스의 초기에만 자주 사용된 페이지의 경우 이후에 더 이상 자주 사용되지 않는다고 할지라도 페이지가 교체되지 않아 오히려 페이지 부재가 발생할 수 있음 1690 | - 이를 극복하기 위해 참조 횟수 비트를 일정 시간마다 오른쪽으로 shift 연산하여 지수적으로 영향력을 감소시키는 방법이 있음 1691 | 1692 | #### MFU 알고리즘(Most-Frequently-Used) 1693 | 1694 | - 가장 적은 참조 횟수를 가진 페이지가 가장 최근에 사용된 페이지이며, 또 앞으로 사용될 것이라 판단하여 교체하지 않는 방법 1695 | 1696 |
1697 | 1698 | ## 프레임 할당 1699 | 1700 | 요구 페이징의 두번째 관건은 프레임 할당입니다. 여러 프로세스에게 각각 얼마나 많은 프레임을 할당해야할지 결정하는 문제이죠. 프레임 할당에 따라 페이지 부재율이 달라질 수 있기때문에 프레임 할당은 페이지 교체와 더불어 중요하게 작용합니다. 다양한 프레임 할당 알고리즘에 대해 소개합니다. 1701 | 1702 | ### 균등 할당 1703 | 1704 | - 모든 프로세스에게 프레임을 똑같이 할당 1705 | - 가장 단순~무식~한 방법으로 작은 크기의 메모리를 요구하는 프로세스는 메모리를 낭비한다는 문제가 있음 1706 | 1707 | ### 비례 할당 1708 | 1709 | - 각 프로세스의 크기에 맞춰 비율대로 할당 1710 | - 프로세스가 요구하는 크기를 고려할 수 있어 균등 할당에서 발생하는 문제를 어느정도 보완할 수 있음 1711 | - 프로세스 크기 대신 프로세스의 우선순위를 기준으로 삼아 비율을 나눠 할당한다면 우선순위가 높은 프로세스에게 더 많은 메모리를 할당하여 프로세스를 빠르게 수행할 수 있음 1712 | 1713 | ### 전역 대 지역 할당 1714 | 1715 | 이제서야 밝히지만 프레임 할당에는 또 다른 중요한 요인이 있습니다. 바로 페이지 교체를 고려하는 것인데, 구체적으로 **전역 교체**와 **지역 교체** 라는 두 가지 범주로 나눌 수 있다는 것입니다. 1716 | 1717 | - 전역 교체 : 프로세스가 교체할 프레임을 다른 프로세스에 속한 프레임을 포함한 모든 프레임을 대상으로 찾음 1718 | - 우선 순위가 높은 프로세스가 낮은 프로세스로부터 프레임을 빼앗아오는 경우 1719 | - 다른 프로세스로부터 프레임을 할당받게 된다면 프로세스에게 할당된 페이지 수도 증가하게 됨 1720 | - 일반적으로 지역 교체 알고리즘보다 우수한 성능을 자랑하여 보편적으로 사용됨 1721 | - 하지만 프로세스의 페이지 부재율을 컨트롤하기 어렵다는 단점이 존재함(페이지 부재율은 다른 프로세스에게 영향을 받는데 전역 교체는 프로세스 간 프레임과 페이지가 교환되기 때문에) 1722 | - 지역 교체 : 각 프로세스가 자신에게 할당된 프레임 내부에서만 교체될 희생자를 찾음 1723 | - 프로세스 개별에게 할당된 프레임에는 변화가 없음 1724 | - 페이지 부재율이 다른 프로세스에 의해 변하거나 조절하기 어려운 문제가 발생하지 않음 1725 | - 다만 전역 교체보다 성능이 좋지 않음 1726 | 1727 |
1728 | 1729 | ## 쓰레싱(Thrashing) 1730 | 1731 | 만약 한 프로세스가 프레임을 부족하게 할당받는다면 페이지 집합도 부족하게 할당받게 될 것이고, 이는 페이지 부재를 발생시킬 것입니다. 하지만 만약 다른 프로세스들도 모두 열심히 일하고 있는 상황이라 페이지를 내어줄 수 없다면 어떻게 될까요? 다른 프로세스로부터 억지로 페이지를 뺏어오더라도 바로 다시 해당 프로세스가 페이지 부재를 발생시켜 결국 페이지를 되돌려줘야하는 문제가 발생할 수 있습니다. 1732 | 1733 | 이와 같은 치열한 눈치싸움, 과도한 페이징 작업을 **쓰레싱**이라 합니다. 쓰레싱은 어떤 프로세스가 실제 실행보다 더 많은 시간을 페이징에 사용하고 있는 것을 말합니다. 쓰레싱이 발생하면 성능은 심각하게 저하됩니다. 1734 | 1735 | 쓰레싱은 전역 페이지 교체 알고리즘을 이용하여 다중 프로그래밍 정도를 높일 때 발생할 수 있습니다. 운영체제는 다중 프로그래밍 정도를 높이기 위해 CPU 이용률이 낮아지면 새로운 프로세스를 추가합니다. 이때 다른 프로세스의 프레임을 할당받는 전역 페이지 교체 알고리즘을 적용한다면 다른 프로세스도 프레임이 부족한 상황에서는 서로의 프레임을 자꾸 할당받으려 할 것입니다. 이 과정에서 CPU는 다시 놀게되고, 운영체제는 더 많은 프로세스를 추가시켜버리는 것이죠. 이러한 악순환이 반복되어 쓰레싱이 발생합니다. 1736 | 1737 | 쓰레싱은 지역 교환 알고리즘 혹은 우선순위 교환 알고리즘을 적용하여 막을 수 있지만, 좀 더 근본적인 해결책은 각 프로세스가 필요로 하는 최소한의 프레임 수를 보장하는 것입니다. 이를 위해서는 **작업 집합 모델**에 대해 이해해야 합니다. 1738 | 1739 |
1740 | 1741 | ### 작업 집합 모델(Working-Set Model) 1742 | 1743 | 작업 집합 모델은 프로세스가 필요로 하는 최소한의 프레임 수를 알 수 있는 방법으로, 쓰레싱을 조절하는 방법 중 하나입니다. 작업 집합 모델은 **지역성** 개념을 기반으로 합니다. 1744 | 1745 | 지역성 모델이란 프로세스가 실행될 때는 **항상 어떤 특정 지역에서만 메모리를 집중적으로 참조**한다는 개념입니다. 이에 따라 지역성은 집중적으로 함께 참조되는 페이지들의 집합을 의미합니다. 1746 | 1747 | 지역성을 고려하여 작업 집합을 구성하는 방법은 다음과 같습니다. 특정 프로세스가 최근 참조한 페이지들 중 Δ개의 페이지를 작업 집합으로 구성합니다. 이후 한 페이지가 더이상 사용되지 않는다면 해당 페이지의 마지막 참조로부터 Δ만큼의 새로운 페이지가 작업 집합으로 구성될 것이고, 사용되지 않는 페이지는 집합에서 제외됩니다. 1748 | 1749 | 작업 집합의 정확도에서 중요한 것은 Δ값, 즉 집합의 크기겠죠. Δ값이 너무 커지면 지역성을 과도하게 수용할 것이고, Δ값이 너무 작아지면 지역을 포함하지 못할 것입니다. 1750 | 1751 | 작업 집합을 설정하게 된다면 운영체제는 각 프로세스의 작업 집합을 통해 프로세스에게 맞는 크기의 프레임을 할당할 수 있습니다. 따라서 가능한 최대의 다중 프로그래밍 정도를 유지하면서도 쓰레싱을 방지할 수 있게됩니다. 1752 | 1753 | 하지만 작업 집합을 추적하는 것이 쉬운 일은 아닙니다. 여기서도 참조 비트를 활용하여 구현해야 합니다. 타이머 인터럽트를 발생시켜 현재 작업 집합의 참조 비트와 이전 단위의 작업 집합의 참조 비트를 비교하는 방식으로 구현할 수 있지만, 이런 방식은 정확도가 낮고 오버헤드가 크다는 문제가 있습니다. 1754 | 1755 |
1756 | 1757 | ### 페이지 부재 빈도(PFF, Page-Fault Frequency) 1758 | 1759 | 쓰레싱을 조절하는 또 다른 방법은 페이지 부재 빈도 모델입니다. 1760 | 1761 | 쓰레싱의 개념에 대해 다시 생각해봅시다. 쓰레싱이 발생했다는 것은 페이지 부재율이 높다는 것을 의미합니다. 페이지 부재율이 높으면 **더 많은 프레임이 할당되어야**하고, 페이지 부재율이 낮으면 **너무 많은 프레임을 할당해 낭비**가 될 수 있습니다. 1762 | 1763 | 따라서 페이지 부재율을 조절해야할텐데, 단순하게 페이지 부재율의 상한과 하한을 설정한다고 생각해봅시다. 페이지 부재율이 상한을 넘어가게 되면 해당 프로세스에게 더 많은 프레임을 할당해주면 됩니다. 또한 하한보다 낮아지게 된다면 해당 프로세스로부터 프레임을 빼앗아 다른 프로세스에게 할당해주면 됩니다. 1764 | 1765 | 페이지 부재 빈도 모델을 통해 직접적으로 페이지 부재율을 관리할 수 있고 쓰레싱도 막을 수 있습니다. 1766 | 1767 |
1768 | 1769 |
1770 | 1771 | # 파일시스템(File System) 1772 | 1773 | 1774 | 1775 |
1776 | 1777 | 1778 | 1779 | ## 파일 시스템(File System) 1780 | 1781 | 파일 시스템은 시스템 상 파일들의 저장, 접근, 공유 등 모든 관리를 총괄하는 시스템이다. 사용자와 보조기억장치 간의 인터페이스를 제공하여 사용자가 직접적으로 파일에 접근하는 것을 막고 대신해서 파일 관련 작업들을 수행해준다. 1782 | 1783 |
1784 | 1785 |
1786 | 1787 | 1788 | 1789 | ## 파일(Files) 1790 | 1791 | 연관된 정보들을 모아놓은 논리적 저장 단위. 운영체제(OS)는 저장 장치의 물리적 특징을 추상화하여 파일로 맵핑하여 관리한다. 일반적으로 비휘발적인 특성을 가져 전원이 끊어져도 영구적으로 보존할 수 있다. 1792 | 1793 |
1794 | 1795 | ### 파일 속성 1796 | 1797 | - 이름: 사용자가 읽고 식별할 수 있는 파일 이름 1798 | 1799 | - 식별자: 파일 시스템에서 파일들을 식별하는 고유 번호 1800 | 1801 | - 타입: 실행파일, 텍스트파일, 소스파일 등 여러 타입 존재 1802 | 1803 | Windows는 이름에 확장자 제공, UNIX는 파일 내에 매직넘버(Magic number) 제공 1804 | 1805 | - 위치 1806 | 1807 | - 크기 1808 | 1809 |
1810 | 1811 | 1812 | ### 파일 연산 1813 | 1814 | 시스템 콜을 통해 파일 관련 여러 연산을 수행할 수 있고 수행 단위에 따라 **파일 단위 작업**과 **레코드 단위 작업**으로 분류할 수 있다. 1815 | 1816 | - 파일 단위 작업 1817 | 1818 | open, close, copy, rename, destroy ... 1819 | 1820 | - 레코드 단위 작업 1821 | 1822 | read, write, update, insert, delete ... 1823 | 1824 | 운영체제는 Open-file table을 사용해 열린 파일들을 관리한다. 파일을 연 횟수, 디스크에서 위치, 접근 관한 등이 기록된다. 각 프로세스들은 각자 file descriptor(fd) table을 가지고 연 파일들의 fd를 관리한다. 1825 | 1826 | 1827 |
1828 | 1829 | 1830 | 1831 | ### 파일 접근 방법 1832 | 1833 | 1. 순차 접근 1834 | 1835 | 기본적인 접근 방법으로 file pointer를 따라 파일 정보가 차례차례 처리된다. read(), write()는 자동으로 file pointer를 변경시키고 lseek()를 사용해 file pointer를 조정할 수 있다. 1836 | 1837 |

1838 |

1839 | 1840 | 2. 직접 접근 1841 | 1842 | file pointer를 직접적으로 조작하여 특별한 순서 없이 빠르게 레코드를 읽고 쓸 수 있다. 대규모 정보를 접근하는 데이터베이스 관리에서 주로 사용된다. 1843 | 1844 | 1845 |

1846 |

1847 | 1848 |
1849 | 1850 |
1851 | 1852 | 1853 | 1854 | 1855 | ## 디렉터리(Directory) 1856 | 1857 | 관련된 파일이나 디렉터리들의 집합으로 사용자는 이를 통해 파일들을 구조화할 수 있다. 디렉터리 또한 파일이나 디렉터리 정보를 담은 하나의 **파일**이다. 1858 | 1859 |
1860 | 1861 | 1862 | ### 1단계 디렉터리 1863 | 1864 | 모든 파일이 동일한 디렉터리에서 관리되는 가장 기본적인 구조. 각 파일은 유일한 이름을 가져야 하므로 다수의 사용자가 사용할 경우 제약이 따른다. 1865 | 1866 |

1867 |

1868 | 1869 | 1870 |
1871 | 1872 | 1873 | ### 2단계 디렉터리 1874 | 1875 | 사용자별로 디렉터리를 생성한 구조. MFD(Master File Directory)가 있고 그 아래에 사용자별로 할당되는 UFD(User File Directory)가 있다. 파일 참조 시 각 UFD만 탐색하므로 사용자별로 파일 이름이 중복될 수 있다. 1876 | 1877 | 1878 |

1879 |

1880 | 1881 |
1882 | 1883 | 1884 | ### 트리 구조 디렉터리 1885 | 1886 | 하나의 루트 디렉터리와 다수의 서브 디렉터리로 구성된 구조이며 Dos, Windows, Unix 운영체제에서 사용한다. 서로 다른 디렉터리 내에서는 파일이나 디렉터리의 이름이 중복될 수 있다. 파일 탐색시 절대 경로(루트 디렉터리를 기준) 또는 상대 경로(현재 디렉터리 기준)를 이용할 수 있다. 1887 | 1888 | 1889 |

1890 |

1891 | 1892 |
1893 | 1894 | 1895 | ### 비순환 그래프 디렉터리 1896 | 1897 | 디렉터리들이 서로 파일을 공유할 수 있도록 허용하는 구조. 절대 경로/상대 경로를 사용해 **링크**라는 디렉터리 항목을 만들 수 있다. 공유된 파일을 삭제하는 경우 빈 곳을 가리키는 고아 포인터(dangling pointer)가 발생할 수 있다. 1898 | 1899 | 1900 |

1901 |

1902 | 1903 |
1904 | 1905 | 1906 | ### 일반 그래프 디렉터리 1907 | 1908 | 1909 |

1910 |

1911 | 1912 | 디렉터리 구조에서 순환(Cycle)을 허용하는 구조. 탐색 알고리즘이 간단해 파일 접근에 용이하나 무한 루프에 빠질 가능성도 있다. 1913 | 1914 |
1915 | 1916 | **하드링크(Hard link)**: 해당 파일을 직접적으로 가리키는 링크. 1917 | 1918 | **심볼릭링크(Symbolic link)**: 가리키는 파일의 경로를 담은 링크. 해당 파일이 삭제되면 고아 링크가 된다. 1919 | 1920 | 1921 | 1922 |
1923 | 1924 | 파일 할당 방식, 파일시스템 종류 1925 | -------------------------------------------------------------------------------- /OS/img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/.DS_Store -------------------------------------------------------------------------------- /OS/img/IPC_Message_passing_shared_memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/IPC_Message_passing_shared_memory.png -------------------------------------------------------------------------------- /OS/img/IPC_message_queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/IPC_message_queue.png -------------------------------------------------------------------------------- /OS/img/IPC_pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/IPC_pipe.png -------------------------------------------------------------------------------- /OS/img/IPC_socket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/IPC_socket.png -------------------------------------------------------------------------------- /OS/img/Thread-share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/Thread-share.png -------------------------------------------------------------------------------- /OS/img/banker's-algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/banker's-algorithm.png -------------------------------------------------------------------------------- /OS/img/context-switching.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/context-switching.jpg -------------------------------------------------------------------------------- /OS/img/fcfs_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/fcfs_gantt.png -------------------------------------------------------------------------------- /OS/img/fcfs_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/fcfs_process.png -------------------------------------------------------------------------------- /OS/img/fifo-page-replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/fifo-page-replace.png -------------------------------------------------------------------------------- /OS/img/hierarchical paging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/hierarchical paging.png -------------------------------------------------------------------------------- /OS/img/interrupt_process.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/interrupt_process.PNG -------------------------------------------------------------------------------- /OS/img/lru-page-replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/lru-page-replace.png -------------------------------------------------------------------------------- /OS/img/opt-page-replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/opt-page-replace.png -------------------------------------------------------------------------------- /OS/img/os-booting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/os-booting.png -------------------------------------------------------------------------------- /OS/img/os-shell-kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/os-shell-kernel.png -------------------------------------------------------------------------------- /OS/img/os.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/os.png -------------------------------------------------------------------------------- /OS/img/paging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/paging.png -------------------------------------------------------------------------------- /OS/img/pcb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/pcb.jpg -------------------------------------------------------------------------------- /OS/img/pcb_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/pcb_create.png -------------------------------------------------------------------------------- /OS/img/preem_sjf_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/preem_sjf_gantt.png -------------------------------------------------------------------------------- /OS/img/preem_sjf_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/preem_sjf_process.png -------------------------------------------------------------------------------- /OS/img/priori_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/priori_gantt.png -------------------------------------------------------------------------------- /OS/img/priority_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/priority_process.png -------------------------------------------------------------------------------- /OS/img/process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/process.png -------------------------------------------------------------------------------- /OS/img/resource-allocation-graph-algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/resource-allocation-graph-algorithm.png -------------------------------------------------------------------------------- /OS/img/resource-allocation-graph1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/resource-allocation-graph1.png -------------------------------------------------------------------------------- /OS/img/resource-allocation-graph2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/resource-allocation-graph2.png -------------------------------------------------------------------------------- /OS/img/role-of-os.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/role-of-os.png -------------------------------------------------------------------------------- /OS/img/rr_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/rr_gantt.png -------------------------------------------------------------------------------- /OS/img/sjf_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/sjf_gantt.png -------------------------------------------------------------------------------- /OS/img/sjf_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/sjf_process.png -------------------------------------------------------------------------------- /OS/img/stsructure-of-os.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/stsructure-of-os.png -------------------------------------------------------------------------------- /OS/img/thread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/thread.png -------------------------------------------------------------------------------- /OS/img/virtual-memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/virtual-memory.png -------------------------------------------------------------------------------- /OS/img/wait-for-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongcheol/CS-study/887dfe26584beb19f9d633ebc42af9c74f67a780/OS/img/wait-for-graph.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CS-study 2 | cs지식을 정리하는 공간 3 | 4 | ## Reopository Rules 5 | 6 | ## Table of Contents 7 | 8 | - [Development Common Sense(개발상식)](#개발상식-) 9 | - [Algorithm(알고리즘)](#알고리즘-) 10 | - [Database(데이터베이스)](#데이터베이스-) 11 | - [Network(네트워크)](#네트워크-) 12 | - [Operating System(운영체제)](#운영체제-) 13 | - [Design Pattern(디자인 패턴)](#디자인-패턴-) 14 | 15 | # 개발상식 [🔍](../../tree/main/CommonSense) 16 | 17 | * 클린코드 & 리팩토링 & 시큐어코딩 18 | * 애자일 19 | * TDD 20 | * DDD 21 | * MSA 22 | * OOP 23 | * OOP의 5가지 설계 원칙 24 | * 함수형 프로그래밍 25 | * DevOps 26 | * 3rd Party 27 | * Git , Github, Gitlab 28 | * REST API 29 | * Parameter vs Argument 30 | * Sync vs Async 31 | * XSS 32 | * 도커와 쿠버네티스 33 | 34 | --- 35 | 36 | # 알고리즘 [🔍](../../tree/main/Algorithm) 37 | 38 | 프로그래밍 대회에서 배우는 알고리즘 문제 해결 전략(a.k.a 종만북)을 기반으로 작성한 목차입니다. 39 | 40 | 1. 알고리즘 분석 41 | 1. 시간 복잡도와 공간복잡도 42 | 2. 알고리즘의 정당성 증명 43 | 2. 알고리즘 설계 패러다임 44 | 1. 완전 탐색 45 | 2. 분할 정복 46 | 3. 동적 계획법 47 | 4. 탐욕법 48 | 5. 조합 탐색 49 | 6. 파라메트릭 서치 50 | 3. 유명한 알고리즘 51 | 1. 정수론 52 | 1. 소수 53 | 2. 유클리드 알고리즘 54 | 3. 모듈라 연산 55 | 4. 이항 계수 56 | 2. 계산 기하 57 | 4. 기초 자료구조 58 | 1. 비트마스크 59 | 2. 부분 합 60 | 3. 선형 자료구조 61 | 4. 큐와 스택, 데크 62 | 5. 문자열 63 | 1. KMP 알고리즘 64 | 6. 해시 65 | 7. B-Tree & B+Tree 66 | 5. 트리 67 | 1. 트리의 구현과 순회 68 | 2. 이진 탐색트리 69 | 3. 우선순위 큐와 힙 70 | 4. 구간 트리 71 | 5. 상호 배타적 집합 72 | 6. 트라이 73 | 6. 그래프 74 | 1. 그래프의 표현과 정의 75 | 2. [DFS 76 | 3. BFS 77 | 4. 최단 경로 알고리즘 78 | 1. 다익스트라 79 | 2. 벨만-포드 80 | 3. 플로이드의 모든 쌍 최단 거리 알고리즘 81 | 5. 최소 스패닝 트리 82 | 1. 크루스칼의 최소 스패닝 트리 알고리즘 83 | 2. 프림의 최소 스패닝 트리 알고리즘 84 | 6. 네트워크 유량 85 | 1. 포드-풀커슨 알고리즘 86 | 2. 에드몬드-카프 알고리즘 87 | 3. 이분 매칭 88 | 7. 정렬 89 | 1. 삽입 정렬 90 | 2. 선택 정렬 91 | 3. 버블 정렬 92 | 4. 병합 정렬 93 | 5. 힙 정렬 94 | 6. 퀵 정렬 95 | 7. 기수 정렬 96 | 8. 계수 정렬 97 | 9. 셸 정렬 98 | --- 99 | 100 | # 데이터베이스 [🔍](../../tree/main/Database) 101 | 102 | 1. 키 103 | 2. SQL - 기초 Query 104 | 3. SQL - JOIN 105 | 4. SQL Injection 106 | 5. SQL vs NoSQL 107 | 6. Anomaly 108 | 7. 인덱스 109 | 8. 트랜잭션(Transaction) 110 | 9. 트랜잭션 격리 수준 111 | 10. 레디스 112 | 11. 이상 현상의 종류 113 | 12. Hint 114 | 13. 클러스터링 115 | 14. 리플리케이션 116 | 15. DB 튜닝 117 | 118 | # 네트워크 [🔍](../../tree/main/Network) 119 | 120 | 1. OSI 7계층 121 | 2. IP 122 | 1. IPv4 123 | 2. IPv6 124 | 3. TCP/IP 125 | 4. UDP 126 | 5. 대칭키 & 공개키 127 | 6. HTTP & HTTPS 128 | 7. Load Balancing 129 | 8. Blocking & Non-Blocking I/O 130 | 131 | --- 132 | 133 | # 운영체제 [🔍](../../tree/main/OS) 134 | 135 | 1. 운영체제란? 136 | 2. 프로세스와 쓰레드 137 | 3. 인터럽트 138 | 4. 시스템 콜 139 | 5. PCB와 Context Switching 140 | 6. IPC 141 | 7. CPU 스케줄링 142 | 8. Deadlocks 143 | 9. Race Condition 144 | 10. 세마포어 & 뮤텍스 145 | 11. 메모리 & 가상 메모리 146 | 12. 파일 시스템 147 | 148 | --- 149 | 150 | # 디자인 패턴 [🔍](../../tree/main/DesignPattern) 151 | 152 | * 디자인 패턴이란? 153 | 154 | 1. 생성 패턴 155 | * Builder 156 | * Prototype 157 | * Factory Method 158 | * Abstract Factory 159 | * Singleton 160 | 2. 구조 패턴 161 | * Bridge 162 | * Decorator 163 | * Facade 164 | * Flyweight 165 | * Proxy 166 | * Composite 167 | * Adapter 168 | 3. 행위 패턴 169 | 170 | * Interpreter 171 | * Template Method 172 | * Chain of Responsibillity 173 | * Command 174 | * Iterator 175 | * Mediator 176 | * Memento 177 | * Observer 178 | * State 179 | * Strategy 180 | * Visitor 181 | -------------------------------------------------------------------------------- /_Interview/README.md: -------------------------------------------------------------------------------- 1 | # 🎙 Interview 2 | 기술 면접 대비 예상 질문 정리 3 | 4 | ## Table of Contents 5 | 6 | - [Development Common Sense(개발상식)](#개발상식-) 7 | - [Algorithm(알고리즘)](#알고리즘-) 8 | - [Database(데이터베이스)](#데이터베이스-) 9 | - [Network(네트워크)](#네트워크-) 10 | - [Operating System(운영체제)](#운영체제-) 11 | - [Design Pattern(디자인 패턴)](#디자인-패턴-) 12 | 13 | # 개발상식 [🔍](../../tree/main/CommonSense) 14 | 15 | 16 | --- 17 | 18 |
19 | 20 | 21 | # 알고리즘 [🔍](../../tree/main/Algorithm) 22 | 23 | ### Q. 퀵 정렬의 최악의 시간 복잡도인 `O(n^2)`를 개선하는 방법? 24 | 25 | 퀵 정렬은 매번 단 하나의 원소를 가진 부분와 나머지 원소들을 가진 부분으로 나뉘는 경우 등, 배열의 초기값이나 피봇의 선택 방법에 따라 최악의 경우 `O(n^2)`의 시간 복잡도를 보일 수 있다. 이를 해결하는 방법은 다음과 같다. 26 | 27 | - pivot이 편향되지 않도록 매번 랜덤한 인덱스에 pivot을 설정한다. 28 | - pivot을 인덱스의 중앙값으로 설정한다. 29 | - 정렬하려는 배열의 원소 수에 따라 삽입 정렬과 퀵 정렬을 함께 사용한다. 30 | 31 | 32 | ### Q. 트라이 맵의 차이는? 트라이 대신 맵을 사용하면 안될까? 33 | 34 | - 트라이는 정렬을 지원한다. (트리맵은 정렬을 지원하지만 해시맵은 지원하지 않음) 35 | - 트라이는 충돌이 발생하지 않는다. (해시맵은 데이터가 많을 경우 충돌이 발생할 가능성이 있음) 36 | - 트라이를 활용해 탐색할 경우 맵보다 시간적 성능이 좋을 수 있다. (트리맵의 경우 이진 검색 트리 형태이므로 탐색 시간 복잡도가 `O(logN)` 임) 37 | - 트라이가 메모리를 더 많이 사용한다. 38 | 39 | 40 | --- 41 | 42 |
43 | 44 | 45 | # 데이터베이스 [🔍](../../tree/main/Database) 46 | 47 | 48 | --- 49 | 50 |
51 | 52 | 53 | # 네트워크 [🔍](../../tree/main/Network) 54 | 55 | 56 | --- 57 | 58 |
59 | 60 | 61 | # 운영체제 [🔍](../../tree/main/OS) 62 | 63 | 64 | --- 65 | 66 |
67 | 68 | 69 | # 디자인 패턴 [🔍](../../tree/main/DesignPattern) 70 | 71 | 72 | --- 73 | 74 |
75 | --------------------------------------------------------------------------------