0%

오늘 한 것

공부한 javaScript 코딩 문제

내적

문제 설명

길이가 같은 두 1차원 정수 배열 a, b가 매개변수로 주어집니다. a와 b의 내적을 return 하도록 solution 함수를 완성해주세요.
이때, a와 b의 내적은 a[0]*b[0] + a[1]b[1] + … + a[n-1]\b[n-1] 입니다. (n은 a, b의 길이)

제한사항

  • a, b의 길이는 1 이상 1,000 이하입니다.
  • a, b의 모든 수는 -1,000 이상 1,000 이하입니다.

나의 답

1
2
3
4
5
6
7
function solution(a, b) {
const answer = a.reduce((acc, cur, idx) => acc + cur * b[idx], 0);
return answer;
}

solution([1, 2, 3, 4], [-3, -1, 0, 2]); // 3
solution([-1, 0, 1], [1, 0, -1]); // -2
1
2
3
4
5
6
7
function solution(a, b) {
const answer = a.reduce((acc, _, idx) => acc + a[idx] * b[idx], 0);
return answer;
}

solution([1, 2, 3, 4], [-3, -1, 0, 2]); // 3
solution([-1, 0, 1], [1, 0, -1]); // -2
  • 현재값을 명시적으로 사용하지 않고 배열 자체에 접근 가능하다.

행렬의 덧셈

문제 설명

행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.

제한 조건

행렬 arr1, arr2의 행과 열의 길이는 500을 넘지 않습니다.

나의 답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function solution(arr1, arr2) {
const answer = [];

for (let i = 0; i < arr1.length; i++) {
answer[i] = new Array();
for (let j = 0; j < arr1[0].length; j++) {
answer[i][j] = arr1[i][j] + arr2[i][j];
}
}

return answer;
}

console.log(
solution(
[
[1, 2],
[2, 3],
],
[
[3, 4],
[5, 6],
]
)
); // [[4,6],[7,9]]
  • 다차원 배열의 경우 동적으로 자동 생성되지 않았다. 때문에 새로운 2차원 배열을 new Array()로 생성 후 값을 할당했다.
1
2
3
function solution(arr1, arr2) {
return arr1.map((v1, idx1) => v1.map((v2, idx2) => v2 + arr2[idx1][idx2]));
}
  • 물론 for가 아닌 map() 메서드를 중첩해서 해결할 수도 있다.

출처: programmers

Nyong’s GitHub

오늘 한 것

공부한 javaScript 코딩 문제

비밀지도

문제 설명

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 “공백”(“ “) 또는 “벽”(“#”) 두 종류로 이루어져 있다.
  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 “지도 1”과 “지도 2”라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  3. “지도 1”과 “지도 2”는 각각 정수 배열로 암호화되어 있다.
  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

입출력 예

1
2
3
4
5
매개변수	값
n 5
arr1 [9, 20, 28, 18, 11]
arr2 [30, 1, 21, 17, 28]
출력 ["#####","# # #", "### #", "# ##", "#####"]
1
2
3
4
5
매개변수	값
n 6
arr1 [46, 33, 33 ,22, 31, 50]
arr2 [27 ,56, 19, 14, 14, 10]
출력 ["######", "### #", "## ##", " #### ", " #####", "### # "]

나의 답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function solution(n, arr1, arr2) {
const arrOr = [];

for (let i = 0; i < n; i++) {
arrOr.push(arr1[i] | arr2[i]);
}

const binaryMap = arrOr
.map((v) => v.toString(2))
.map((v) => {
const { length } = v.length;
if (length !== n) {
for (let i = 0; i < n - length; i++) {
v = "0" + v;
}
}
return v;
});

return binaryMap.map((v) =>
v
.split("")
.map((char) => (char === "1" ? "#" : " "))
.join("")
);
}

console.log(solution(6, [46, 33, 33, 22, 31, 50], [27, 56, 19, 14, 14, 10]));
// ["######", "### #", "## ##", " #### ", " #####", "### # "]
  • 2진수로 변환 시 꼭 n 자리 수가 아닐 수 있다는 걸 간과했었다.

감탄한 타인의 답

1
2
3
4
5
6
7
8
9
10
11
function solution(n, arr1, arr2) {
return arr1.map((v, i) =>
addZero(n, (v | arr2[i]).toString(2)).replace(/1|0/g, (a) =>
+a ? "#" : " "
)
);
}

const addZero = (n, s) => {
return "0".repeat(n - s.length) + s;
};

출처: programmers

Nyong’s GitHub

오늘 한 것

공부한 javaScript 코딩 문제

K번째수

문제 설명
배열 array의 i번째 숫자부터 j번째 숫자까지 자르고 정렬했을 때, k번째에 있는 수를 구하려 합니다.

예를 들어 array가 [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3이라면

array의 2번째부터 5번째까지 자르면 [5, 2, 6, 3]입니다.
1에서 나온 배열을 정렬하면 [2, 3, 5, 6]입니다.
2에서 나온 배열의 3번째 숫자는 5입니다.
배열 array, [i, j, k]를 원소로 가진 2차원 배열 commands가 매개변수로 주어질 때, commands의 모든 원소에 대해 앞서 설명한 연산을 적용했을 때 나온 결과를 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • array의 길이는 1 이상 100 이하입니다.
  • array의 각 원소는 1 이상 100 이하입니다.
  • commands의 길이는 1 이상 50 이하입니다.
  • commands의 각 원소는 길이가 3입니다.

입출력 예

[2,6,8,14] -> 168
[1,2,3] -> 6

나의 답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function solution(array, commands) {
const answer = commands.map(
(command) =>
array.slice(command[0] - 1, command[1]).sort((a, b) => a - b)[
command[2] - 1
]
);
return answer;
}

console.log(
solution(
[1, 5, 2, 6, 3, 7, 4],
[
[2, 5, 3],
[4, 4, 1],
[1, 7, 3],
]
)
); // [5, 6, 3]
  • 비교적 간단한 문제
  • 메서드 체이닝을 과하게 사용한 것 같다. 가독성이 떨어진다.

Refactoring

1
2
3
4
5
6
7
8
9
10
11
12
13
function solution(array, commands) {
const answer = commands.map((commend) => {
const [sPosition, ePosition, position] = commend;

const slicedArr = array
.slice(sPosition - 1, ePosition)
.sort((a, b) => a - b);

return slicedArr[position - 1];
});

return answer;
}
  • 위 코드가 가독성이 더 높아보인다.
  • 억지로 간결하게 만든 코드보다는 보기 편안한 코드가 더 좋다.

음양 더하기

문제 설명
어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.

제한 사항

  • absolutes의 길이는 1 이상 1,000 이하입니다.
    • absolutes의 모든 수는 각각 1 이상 1,000 이하입니다.
  • signs의 길이는 absolutes의 길이와 같습니다.
    • signs[i] 가 참이면 absolutes[i] 의 실제 정수가 양수임을, 그렇지 않으면 음수임을 의미합니다.

입출력 예

absolutes / signs
[4,7,12] [true,false,true] -> 9
[1,2,3] [false,false,true] -> 0

나의 답

1
2
3
4
5
6
7
function solution(absolutes, signs) {
const answer = absolutes.map((v, i) => (signs[i] ? v : -v));

return answer.reduce((acc, cur) => acc + cur, 0);
}

console.log(solution([4, 7, 12], [true, false, true])); // 9
  • 비교적 간단한 문제

출처: programmers

Nyong’s GitHub

오늘 한 것

공부한 javaScript 코딩 문제

N개의 최소공배수

문제 설명
두 수의 최소공배수(Least Common Multiple)란 입력된 두 수의 배수 중 공통이 되는 가장 작은 숫자를 의미합니다.
예를 들어 2와 7의 최소공배수는 14가 됩니다. 정의를 확장해서, n개의 수의 최소공배수는 n 개의 수들의 배수 중 공통이 되는 가장 작은 숫자가 됩니다.
n개의 숫자를 담은 배열 arr이 입력되었을 때 이 수들의 최소공배수를 반환하는 함수, solution을 완성해 주세요.

제한 사항

  • arr은 길이 1이상, 15이하인 배열입니다.
  • arr의 원소는 100 이하인 자연수입니다.

입출력 예

[2,6,8,14] -> 168
[1,2,3] -> 6

나의 답

1
2
3
4
5
6
7
8
9
10
11
12
13
function solution(arr) {
const maxNum = arr[arr.length - 1];

for (let i = 1; ; i++) {
let LCM = maxNum * i;

for (let j = 0; j < arr.length; j++) {
if (LCM % arr[j] !== 0) break;

if (j === arr.length - 1) return LCM;
}
}
}
  • 비교적 간단한 문제였다.

출처: programmers

Nyong’s GitHub

오늘 배운 것

Snippet

https://snippet-generator.app/

설정 → 사용자 코드조각 → html 등 언어 설정 → json 형식으로 붙여넣기

React

컴포넌트 네이밍 컨벤션

1
HTML <button type="button" class="button">HTML 버튼 요소</button>
1
2
React Component (JSX)
<Button>React 버튼 요소</Button>

TitleCase 문법 사용을 권장

React ver 17

React 17 버전부터는 함수 컴포넌트에 대해 import React를 할 필요가 없다. 다만 class 컴포넌트에 대해서는class UploadButton extends React.Component 와 같은 경우를 위해 import React해야한다.

SVG Format

SVG는 코드로 이루어진 이미지 디자인 포멧이다. 디자인 포멧이지만 XML과 유사한 코드로 이뤄져있다. 그렇기 때문에 서버 통신에서 가장 큰 용량 중 하나를 차지하는 이미지 파일에 대한 사용을 줄이고 재사용이 가능해진다.

타입 검사

JS 타입 검사

1
2
3
4
5
6
7
// 데이터 타입 검사 유틸리티 함수
function validType(dataType, typeString) {
return (
Object.prototype.toString.call(dataType).slice(8, -1).toLowerCase() ===
typeString
);
}

Object.prototype.toString.call(dataType) 를 사용하면 정확한 타입을 알 수 있다. (Array, function, null 등이 object로 출력되는 type of 보다 직관적이다.

React 타입 검사

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 타입 검사를 위한 객체
const PropTypes = {
string(props, propName, componentName) {
const value = props[propName];
const valueType = typeof value;
const expectedType = "string";

if (valueType !== expectedType) {
const errorMessage = `${componentName} 컴포넌트에 전달 된 ${propName}
${expectedType} 데이터 유형이 전달되어야 하나,
실제 전달된 속성 값 데이터 유형은 ${valueType}입니다. 확인해주세요.`;

return new Error(errorMessage);
}
},
};

/* -------------------------------------------------------------------------- */

export default function SVGIcon({ src, alt, className, ...restProps }) {
return (
<img
src={`${src}.svg`}
alt={alt}
className={`icon ${className}`.trim()}
{...restProps}
/>
);
}

SVGIcon.defaultProps = {
className: "",
};

// React 컴포넌트는 React에 의해
// 전달 속성(props)의 타입을 검사할 수 있는
// propTypes 속성을 제공합니다.
SVGIcon.propTypes = {
src: PropTypes.string,
// alt(){}
};

하지만 이미 React에서 제공하는 타입 검사 prop-types가 있다.

prop-types

npm i -D prop-types 로 설치할 수 있다.

1
2
3
4
5
6
import { string, number, bool } from "prop-types";

SVGIcon.propTypes = {
src: string.isRequired, //필수
alt: string,
};

Nyong’s GitHub

오늘 배운 것

DB

DDL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# DDL : 데이터 정의어
# CREATE, ALTER, DROP
# DB와 테이블을 조작
create database test;
use test;
select database();

# alter : 데이터 베이스나 테이블 수정
show variables like "character_set_database";
alter database test character set = utf8;
desc user;

# alter ADD : 테이블에서 컬럼 추가
alter table user add age int;
desc user;

# alter MODIFY : 테이블에서 컬럼 수정
alter table user modify age char(3);
desc user;

# DROP : 데이터 베이스나 테이블 삭제
truncate money; # 테이블 초기화
select * from money;
drop table money;
show tables;

JOIN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# JOIN : 테이블과 테이블을 결합해서 출력하는 방법

create table user (
user_id int primary key auto_increment,
name varchar(20) default null
);
create table addr (
addr_id int primary key auto_increment,
addr varchar(20),
user_id int
);
insert into user(name) values ("jin"), ("po"), ("alice");
select * from user;
insert into addr(addr, user_id) values ("seoul", 1), ("busan", 2), ("daegu", 4), ("seoul", 5);
select * from addr;

# INNER JOIN
select user.user_id, user.name, addr.addr from user join addr on user.user_id = addr.user_id;
select * from user join addr;

# LEFT JOIN
select user.user_id, user.name, addr.addr from user left join addr on user.user_id = addr.user_id;
select addr.user_id, user.name, addr.addr from addr left join user on user.user_id = addr.user_id;

# RIGHT JOIN
select user.user_id, user.name, addr.addr from user right join addr on user.user_id = addr.user_id;
select user.user_id, user.name, addr.addr from addr right join user on user.user_id = addr.user_id;

# world DB에서 국가코드, 도시이름, 국가이름, 국가인구, 도시인구 출력
use world;
select code, city.name as city_name, country.name as country_name,
country.population as country_pop, city.population as city_pop,
round(city.Population/country.population * 100, 2) as rate
from country join city on country.code = city.CountryCode having rate >= 20 order by rate desc;

# 국가별 언어별 사용 인구를 출력
select country.name, countrylanguage.language, round(country.population * countrylanguage.percentage * 0.01) as lp
from country join countrylanguage on country.code = countrylanguage.CountryCode;

# INNER JOIN 시에 단축할 수 있음
select country.name, countrylanguage.language, round(country.population * countrylanguage.percentage * 0.01) as lp
from country, countrylanguage where country.code = countrylanguage.CountryCode;

# 대륙별 사용언어의 수를 출력
select distinct(country.continent), count(countrylanguage.language)
from country join countrylanguage on country.code = countrylanguage.CountryCode
group by continent;

UNION

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# UNION : 두개의 쿼리를 실행하고 나온 결과를 합쳐주는 방법
# 중복된 데이터를 제거하여 출력한다
use test;
select name from user union all select addr from addr;

select user.user_id, user.name, addr.addr
from user
left join addr
on user.user_id = addr.user_id;

select addr.user_id, user.name, addr.addr
from user
right join addr
on user.user_id = addr.user_id;

sub Query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# sub query : 쿼리안에 쿼리가 있는 문법
# select, from, where

# select : 전체 나라수, 전체 도시수, 전체 언어수 출력 (한개의 row로)
use world;
select
(select count(*) from country) as total_country,
(select count(*) from city) as total_city,
(select count(distinct(language)) from countrylanguage) as total_language
from dual;

# FROM : 800만 이상이 되는 도시의 국가코드, 국가이름, 도시이름, 도시인구수 출력
# JOIN만 사용
# join은 테이블 끼리의 join을 먼저 실행하기 때문에 모든 조합을 만들고 조건에 따라 filter함
select country.code, country.name, city.name, city.population
from city join country on city.countrycode = country.code having city.population >= 800 * 10000;

# sub query 사용
# join과 다르게 처음부터 조건에 맞는 조합만을 만들기 때문에 서브 쿼리문을 잘 활용하면 효율적인 SQL문 작성이 가능하다.
select country.code, country.name, city.name, city.population
from (select countrycode, name, population from city where population >= 800 * 10000) as city
join country on city.countrycode = country.code having city.population >= 800 * 10000;

# where : 900만 이상의 인구가 있는 도시의 국가코드, 국가이름, 대통령 이름 출력

select code, name, headofstate from country
where code in (select countrycode from city where population >= 900*10000);

ANY / ALL

1
2
3
4
5
6
# ANY(OR) / ALL(AND)
# 한국이나 브라질 보다 인구수가 많은 국가의 국가코드, 국가이름, 인구수 출력
select code, name, population
from country
where population > ANY (
select population from country where code in ("KOR", "BRA"));

Nyong’s GitHub

오늘 배운 것

DB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
use fds;

# 데이터 타입
# INT
create table number1(data tinyint);
create table number2(Data tinyint unsigned);

# 현재 데이터 베이스의 테이블 확인
show tables;

# 테이블 스키마 확인
desc number1;
desc number2;

# 데이터 저장
insert into number1 value (127);
select * from number1;

insert into number2 value (128);
insert into number2 value (-1); # unsigned에서는 음수는 넣지 못 한다.
select * from number2;

# FLOAT(6자리), DOUBLE(17자리)
create table number3(data float);
insert into number3 value (12.3456789);
select * from number3;

create table number4(data double);
insert into number4 value (1234567890.123456789);
select * from number4;

# DB 생성
create database test;
use test;

# 테이블 생성
create table user1(
user_id int,
name varchar(20),
email varchar(30),
age int,
rdate date
);

create table user2(
user_id int primary key auto_increment,
name varchar(20) not null,
email varchar(30) unique,
age int default 30,
rdate timestamp
);

# INSERT
desc user1;
insert into user1 (user_id, name, email, age, rdate)
value (1, 'peter', 'peter@gmail.com', 23, '2018-01-23');

insert into user1 (user_id, name, email, age, rdate)
values (2, 'peter2', 'peter@gmail.com', 23, '2018-01-23'),
(3, 'peter3', 'peter@gmail.com', 23, '2018-01-23'),
(4, 'peter4', 'peter@gmail.com', 23, now());

select * from user1;

desc user2;
insert into user2 (name, email, age)
value ('peter', 'peter@gmail.com', 22);

select * from user2;

# select 결과 데이터
use world;

select countrycode, name, population from city where population >= 900* 10000;

create table city_900(
countrycode char(3),
name varchar(50),
population int
);
desc city_900;

insert into city_900
select countrycode, name, population from city where population >= 900* 10000;

select * from city_900;

# update set
use test;

select * from user1;

# update 시 safe mode로 인해 limit을 안 걸면 update 되지 않는다.
#설정 SQL Editor에서 설정 가능
update user1 set age=50, email="peter@naver.com" where name = "peter" limit 3;

# DELETE

select * from user1;

delete from user1 where rdate > '2018-01-23' limit 5;

# 실행 중인 process 보기와 중단
show processlist;
kill 154;

# TRUNCATE : 스키마만 남기고 모두 삭제(DDL)
select * from user1;
truncate user1;

# DROP : 테이블 삭제
drop table user1;
show tables;

# Functions
select ceil(12.345), round(12.345, 2), truncate(12.345, 2);

# date_format
use sakila;
select date_format(payment_date, "%Y-%m") from payment;

# concat
use world;
select code, name, concat(code, "/", name) from country;

# count
select count(*) from country;
select count(distinct(continent)) from country;

# if
# 도시의 인구가 100만 이상이면 big, 100만 미면 small 출력하는 컬럼을 생성
select name, population, if(population > 100*10000, "big", "small") as scale from city;

# case
# 국가별 인구가 10억 이상(big), 1억 이상 (medium), 1억 이하는 (small)
select name, population,
case
when population >= 100000 * 10000 then 'big'
when population >= 10000 * 10000 then 'medium'
else 'small'
end as scale
from country order by population desc;

# GROUP BY, HAVING
# 여러개의 동일한 데이터를 가지는 지정한 컬럼의 데이터를 합쳐주는 방법
# 결합함수 : count, max, min, sum, avg ...

#city 테이블에서 국가코드별 도시의 개수 출력
select countrycode, count(countrycode) as count from city group by countrycode order by count desc;

# country 테이블에서 대륙별 총 인구수 출력 3위까지 출력
select continent, sum(population) as total_population from country group by continent order by total_population desc limit 3;

# having
# 대륙의 인구수가 5억 이상인 대륙만 출력
select continent, sum(population) as total_population from country group by continent having total_population >= 500000000;

select ifnull(continent, 'total'), ifnull(region, 'total'), count(region) from country group by continent, region with rollup;

# 변수 선언
set @data = 1;
select @data;

set @rank =0;
select @rank := @rank + 1 as ranking, countrycode, name, population from city order by population desc limit 5;

# 외례키
# 데이터의 무결성을 지키기 위한 제약조건
use test;
drop table user2;

# 아래는 무결성이 깨지는 경우
create table user(
user_id int primary key auto_increment,
name varchar(20),
addr varchar(20)
);

create table money(
money_id int primary key auto_increment,
income int,
user_id int
);

insert into user(name, addr) values ('po', 'seoul'), ('jo', 'pusan');
select * from user;

insert into money(income, user_id) values (5000, 1), (6000, 3);
select * from money;

# 테이블을 생성할 때 설정, 무결성을 위한 외례키
drop table money;

create table money(
money_id int primary key auto_increment,
income int,
user_id int,
foreign key (user_id) references user(user_id)
);
insert into money(income, user_id) values (5000, 1), (6000, 3); # user_id가 서로 맞지 않으면 에러 발생
insert into money(income, user_id) value (5000, 1);
select * from money;

# 테이블 생성 후 수정해서 설정
drop table money;

create table money(
money_id int primary key auto_increment,
income int,
user_id int
);
alter table money add constraint fk_user foreign key (user_id) references user (user_id);
desc money;
insert into money(income, user_id) values (5000, 1), (6000, 3); # user_id가 서로 맞지 않으면 에러 발생
insert into money(income, user_id) value (5000, 1);
select * from money;

# user(1, 2), money(1, 2)
delete from user where user_id =1 limit 10; # 무결성을 위해 서로 참조하는 데이터는 삭제가 불가능

# on delete, on update 설정
# cascade : 참조되는 테이블에서 데이터를 삭제하거나 수정하면 참조하는 테이블에서도 삭제, 수정한다.
# set null : 삭제, 수정하면 참조하는 테이블에서는 null로 바뀐다.
# no action : 참조하는 테이블에서 삭제하거나 수정하면 변경되지 않는다.(무결성이 깨지기 때문에 지양)
# set default : 참조하는 테이블에서 삭제하거나 수정하면 기본값으로 설정된다.
# restrict : 삭제, 수정에 대해 불가능하게 본다. (strict mode)

# 업데이트되면 같이 업데이트, 삭제되면 null로 변경
# on update > cascade, on delete > set null 설정
drop table money;

create table money(
money_id int primary key auto_increment,
income int,
user_id int,
foreign key (user_id) references user(user_id)
on update cascade on delete set null
);
insert into money(income, user_id) values (5000, 1), (6000, 2);
select * from money;

update user set user_id = 3 where user_id = 2 limit 1;
select * from user;

delete from user where user_id = 3 limit 1;

Nyong’s GitHub

오늘 배운 것

DB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use world;

# SELECT: 데이터 조회
select * from country;

select code, name, continent, population from country;

select countrycode as code, name from city;

# where : 조건으로 데이터를 검색
# 인구가 1억명이 넘는 국가의 국가코드와 국가이름, 인구수를 출력

select code, name, population from country where population >= 100000000;

# mysql 주석
-- 한줄 주석alter
/*
여러줄 주석
*/

# 연산자 : 산술, 비교, 논리
# 산술 : +. -. *, /, %, DIV(몫)

# 인구밀도
select name, surfaceArea, population, population / surfacearea as pps from country;

# 국가별 1인당 GNP 출력
select name, gnp, population, gnp / population * 1000000 as gpp from country;

# 비교 연산자
# =, !=, >, <, >=, <=
select name, population from city where population >= 800*10000;

# 논리연산자 : AND, OR
select name, population from country where population >= 800*10000 and population <= 1000*10000;
# BETWEEN : 범위 연산 시 사용
select name, population from country where population between 800*10000 and 1000*10000;

# 아시아와 아프리카가 대륙의 국가 데이터 출력
select name, continent from country where continent = 'asia' OR continent = 'africa';

# IN, NOT IN : 컬럼에 여러개의 데이터를 포함하는 데이터를 출력할 때
select name, continent from country where continent in ('asia', 'africa');

# LIKE : 특정한 문자열이 포함된 데이터를 출력
# governmentform 이 Republic 포함된 데이터를 출력
select name, governmentform from country where govermentform like "%Republic%";

# 국가 코드가 ar로 시작하는 국가의 이름을 출력
select code, name from country where code like "ar%";

# ORDER BY : 결과 데이터 정렬
# asc: 오름차순(생략 가능)
select code, name, gnp from country order by gnp asc;

# desc: 내림차순
select code, name, gnp from country order by gnp desc;

# 국가 코드 순으로 내림차순, 같은 국가 코드는 인구수 순으로 오름차순 정렬
select countrycode, name, population from city order by countrycode desc, population asc;

# LIMIT : 조회하는 데이터 수를 제한
# 인구가 많은 상위 5개 국가의 이름, 인구수 출력
select name, population from country order by population desc limit 5;

# 인구수가 상위 5위에서 8위까지 출력
select name, population from country order by population desc limit 5, 4;

# DISTINCT : 출력되는 데이터에서 중복을 제거해서 출력
select distinct continent from country

Nyong’s GitHub

오늘 배운 것

OS

kernel

컴퓨터 공학에서 말하는 OS는 커널(Kernel)이다.

시스템 콜은 OS의 기능을 사용할 수 있도록 커널이 제공해주는 함수 또는 명령이다.

프로그래밍 언어 별로 시스템 콜을 호출하는 API를 갖는다.

프로그램에서 커널 모드에서만 실행할 수 있는 기능을 사용해야할 경우, API를 통해 시스템 콜을 호출하게 되면 프로그램은 커널에 의해서 커널 모드로 바뀌며 커널만 사용할 수 있는 명령어를 실행 후 사용자 모드로 돌아간다.

프로세스

실행 중인 프로그램 = 프로세스

실행 중인 프로그램은 메모리에 올려진 상태

Batch Processing

순차적으로 프로그램을 실행한다.

앞서 실행 중인 프로그램에 시간 소모가 많다면 효율이 떨어진다.

시분할 시스템(Time Sharing)

하나의 컴퓨터에서 다중 사용자 지원을 위해 CPU를 10ms 단위로 나눠서 각각의 프로세스들을 교체하며 처리한다.

멀티 태스킹

개인 사용자가 실시간으로 다중 프로세스들을 동시에 처리하는 것 처럼 보이는 프로세스 스케쥴링 방식이다. (10~20ms 단위로 응용 프로그램을 바꾸며 실행한다.)

멀티 프로그래밍

단위 시간 당 응용프로그램을 최대한 많이 실행시키는(최대한 CPU 활용) 프로세스 스케쥴링 기법이다.

메모리 계층

Register - Cache - Memory - Disk

메모리 계층에 따라 데이타 로드에 따른 시간이 다르다.

Register가 가장 빠르며 HardDisk와 같은 저장매체가 가장 느리다.

멀티 프로그래밍과 Wait

위의 메모리 계층에 의해 발생하는 대기 시간에 따라 CPU 활용도를 극대화 하기 위해 사용하는 것이 멀티 프로그래밍 스케쥴링 알고리즘이다.

Wait: 저장매체의 로드 대기 시간

멀티 태스킹과 멀티 프로세싱

멀티 태스킹은 단일 CPU에서 여러 프로세스를 스케쥴링하는 것이다.

멀티 프로세싱은 여러 CPU가 하나의 프로그램을 병렬 처리하여 실행 속도를 극대화하는 것이다.

Nyong’s GitHub

오늘 배운 것

TypeScript

타입 변환 방법, 변수 선언식에도 타입을 지정하기 보다는 값에 대한 타입으로 변수 타입 추론을 활용하는 것이 좋다.

1
2
3
4
5
const $foo = document.querySelector("input[text]") as HTMLInputElement;
const val = $foo.value;

const $bar = <HTMLInputElement>document.querySelector("input[text]");
const va = $bar.value;

앨리어스와 interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 앨리어스
type TodoType = {
id: number;
content: string;
completed: boolean;
};

// 인터페이스
interface Todo {
id: number;
content: string;
completed: boolean;
}

const todos: Todo[] = [{ id: 1, content: "HTML", completed: false }];

const addTodo = (todo: Todo) => {
todos = [...todos, todo];
};

앨리어스와 interface 모두 객체에 대한 타입이기 때문에 파스칼 케이스를 사용한다.

interface의 경우 implements를 사용할 수 있다.

인터페이스의 프로퍼티가 선택적으로 필요한 경우 선택적 프로퍼티(Optional Property)는 프로퍼티명 뒤에 ?를 붙이며 생략하여도 에러가 발생하지 않는다.

1
2
3
4
5
6
7
8
9
10
11
interface UserInfo {
username: string;
password: string;
age?: number;
address?: string;
}

const userInfo: UserInfo = {
username: "ungmo2@gmail.com",
password: "123456",
};

제네릭

같은 형식에서 타입만 달라질 경우 반복되는 코드를 짜기보다는 제네릭을 활용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 인터페이스
interface Todo {
id: number;
content: string;
completed: boolean;
}

// 제네릭 형식
const todos: Array<Todo> = [{ id: 1, content: "HTML", completed: false }];

const addTodo = (todo: Todo) => {
todos = [...todos, todo];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Queue<T> {
protected data: Array<T> = [];
push(item: T) {
this.data.push(item);
}
pop(): T | undefined {
return this.data.shift();
}
}

// number 전용 Queue
const numberQueue = new Queue<number>();

// string 전용 Queue
const stringQueue = new Queue<string>();

// 커스텀 객체 전용 Queue
const myQueue = new Queue<{ name: string; age: number }>();

Nyong’s GitHub