-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathdb.json
181 lines (181 loc) · 19.9 KB
/
db.json
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
{
"backend": {
"1": {
"quiz": "네트워크 소켓이란 무엇인가요?",
"answer": "네트워크 소켓이란 응용 프로그램이 전송 계층에 접근할 수 있도록 파일 형식으로 추상화한 인터페이스입니다. 네트워크로 연결된 컴퓨터(호스트) 간 통신하기 위해 필요합니다.",
"contributor": [],
"category": ["네트워크"]
},
"2": {
"quiz": "웹 서버 환경에서 보편적으로 CPU 부하 분산보다 I/O 부하 분산처리가 더 어려운 이유는 무엇인가요?",
"answer": "CPU 부하의 경우 서버를 추가하고 로드 밸런서로 부하를 균등하게 분산해 비교적 간단하게 해결할 수 있습니다.\n\n그러나 I/O 부하의 경우 입출력 요청을 여러 기기에서 사용하기 때문에 동시성에 대한 고려가 추가적으로 필요합니다.\n",
"contributor": [],
"category": ["시스템 디자인"]
},
"3": {
"quiz": "A 레코드와 CNAME 레코드, MX 레코드에 대해 들어보신 적 있으신가요?",
"answer": "언급하신 키워드는 모두 DNS 레코드 종류들입니다\nDNS 레코드들은 DNS 서버가 해당 패킷을 받았을 때 도메인 이름을 IP로 매핑하기 위해 처리할 방법에 대해 지침합니다\n\"A 레코드\"는 IPv4 주소를 가진 호스트를 찾기 위해 사용됩니다\n\"CNAME 레코드\"는 한 도메인에 alias를 부여해 다양한 도메인으로 접근할 수 있도록 할 때 사용됩니다\n\"MX 레코드\"는 수신할 메일의 메일 서버를 찾기 위해 사용됩니다\n언급하신 키워드 외에도 AAAA레코드, NS 레코드, SOA 레코드, PTR 레코드, TXT 레코드, SRV 레코드 등이 있습니다\n",
"contributor": [],
"category": ["네트워크"]
},
"4": {
"quiz": "인덱스를 구성할 때 이진트리가 아닌 B+트리를 사용했을 때의 장점은 무엇이 있을까요?",
"answer": "1. B+트리는 갱신작업 후에 트리 구조가 스스로 변하기 때문에 O(logN)의 검색 속도를 보장합니다. 이진트리의 경우 노드 값에 의한 재정렬을 하지 않기 때문에 최악의 경우 선형 탐색 O(N)의 성능을 가집니다.\n\n2. B+트리는 노드당 데이터 수를 변경할 수 있어, 노드의 크기를 조절할 수 있습니다. 따라서, 노드 크기를 4KB 혹은 8KB인 페이지 크기로 만들어 디스크 IO를 최소화할 수 있습니다.\n\n3. B+트리는 리프 노드가 링크드 리스트로 연결되어 있어 인접한 노드들에 대해 순차적으로 접근할 수 있습니다. 따라서 디스크 랜덤 읽기가 아닌 순차 읽기가 가능합니다. 이로 인해 디스크 I/O가 줄어들어 빠른 속도를 보장합니다.\n",
"contributor": [],
"category": ["데이터베이스"]
},
"5": {
"quiz": "DB가 JOIN을 수행하는 방법에는 어떠한 것들이 있을까요?",
"answer": "NL(Nested Loop), Sort-Merge, Hash 방식이 있습니다\nNL은 드라이빙 테이블의 조건 컬럼에 해당하는 레코드 1건마다 드리븐 테이블 조건 컬럼을 각각 탐색해 반복문 형태를 취하는 조인 형태입니다. 가장 많이 쓰이는 형태의 조인이며, 드라이빙 테이블에서 드리븐 테이블의 조건 레코드 수 만큼 검색하므로 주로 드라이빙 테이블보다 드리븐 테이블의 레코드 수가 많을 때 성능이 좋습니다\n\nSort-Merge는 조건에 맞는 행을 찾아 정렬한 뒤 비교하는 방식입니다\n\nHash은 조인 대상 테이블 중 레코드 수가 적은 테이블을 해시 테이블로 만들어 조인을 수행합니다\n\n주로 응답 속도가 중요한 OLTP 연산에선 NL, 처리량이 많이 필요한 방식에선 Hash가 유용합니다",
"contributor": [],
"category": ["데이터베이스"]
},
"6": {
"quiz": "컴퓨터를 막 부팅했을 때, 컴퓨터 성능이 느린 이유는 무엇일까요?",
"answer": "프로세스는 기본적으로 메모리에 올라와 있는 정보만 이용할 수 있습니다\n\n그러나 메모리는 휘발성 영역이기 때문에 컴퓨터 전원을 껐다가 켰을 경우 캐싱되어 있는 데이터가 없기 때문에 디스크로부터 필요한 읽기 작업을 수행한 후에 일정한 성능을 얻을 수 있습니다.",
"contributor": [],
"category": ["운영체제"]
},
"7": {
"quiz": "트랜잭션 격리 수준에서 Read Committed와 Repeatable Read 수준의 차이점은 무엇일까요?",
"answer": "Read Committed 수준은 Oracle에서 기본으로 사용되며, 아직 커밋되지 않은 트랜잭션에서 수정한 데이터를 읽을 수 있는 \"Dirty Read\" 문제를 해결합니다. 그러나 다른 트랜잭션에서 수정하고 커밋 완료한 경우 현재 트랜잭션에서 다시 읽은 값이 달라질 수 있는 \"Non-Repeatable Read\"라는 문제가 발생합니다\n\nRepeatable Read 격리 수준은 MySQL의 InnoDB에서 기본으로 사용되며 트랜잭션 마다 버전을 기입해서 현재 트랜잭션보다 낮은 버전의 데이터만 보게 해 Non-Repeatable Read 문제를 해결합니다. 그러나 쓰기 잠금을 거는 경우 다른 트랜잭션에 의해 수정된 레코드가 보이기도 하는 \"Phantom Read\"라는 현상을 겪을 수도 있습니다\n",
"contributor": [],
"category": ["데이터베이스"]
},
"8": {
"quiz": "InnoDB의 경우 Repeatable Read 수준에서도 Phantom Read 현상이 발생하지 않는 이유가 무엇인가요?",
"answer": "InnoDB는 레코드 단위의 인덱스 레코드 락을 제공하는데 이때 갭 락을 사용합니다. 갭 락은 목적 레코드 사이에 모두 읽기 잠금을 걸기 때문에 쓰기 작업을 수행할 수 없어 Phantom Read 현상이 발생하지 않습니다\n\n별개로, 갭 락은 데드락 현상의 주원인이기도 하므로 가능한 줄이는 것이 좋습니다",
"contributor": [],
"category": ["데이터베이스"]
},
"9": {
"quiz": "네트워크를 통해 인터넷으로 데이터를 전송할 때의 흐름을 프로세스부터 설명해 보시겠어요?",
"answer": "애플리케이션 프로세스에서 Socket에 \"Stream\" 데이터를 쓰기 작업해 전송 계층으로 보냅니다.\n\n전송 계층에서는 Stream 데이터를 MSS(Maximum Segment Size)를 기준으로 잘라 \"Segment\"로 만드는 \"Segmentation\" 후 Network 계층으로 보냅니다.\n\nNetwork 계층에서 Segment를 인터넷으로 전송 가능한 형태의 default 1500 byte인 \"Packet\"으로 만들어 데이터 링크 계층으로 보냅니다.\n\n데이터 링크 계층에서는 패킷을 \"Frame\"으로 \"Encapsulation\"해 인터넷으로 전송합니다.\n\n참고 : https://www.youtube.com/watch?v=p6ASAAMwgd8",
"contributor": [],
"category": ["네트워크"]
},
"10": {
"quiz": "HTTP 프로토콜이란 무엇인가요?",
"answer": "HTTP란 Hyper Text Transfer Protocol의 약자입니다. 이는 HTML파일을 주고받기 위한 약속이며, HTML을 요청하는 주체를 클라이언트라고 부르고 제공하는 주체를 웹 서버라고 부릅니다.\n\n클라이언트는 보편적으로 브라우저 형태를 띄며 추가적으로 동적으로 변화하는 데이터에 대한 정보를 제공하는 서버를 WAS라고 부릅니다.\n\nHTTP는 보편적으로 TCP/IP 기반이고 버전 별로 0.9 / 1.0 / 1.1 / 2.0 / 3.0이 있으며 공식 표준 버전은 1.1입니다. \n\nHTTP 프토콜은 클라이언트가 요청하면 서버가 응답하는 형태를 띄며, 패킷에는 원하는 동작인 \"메서드\", 서버의 위치인 \"주소\", \"HTTP 버전\", 요청에 대한 추가 정보인 \"헤더\", 본문인 \"body\"가 들어있습니다.\n\n응답 리퀘스트의 경우 요청 결과를 나타내는 \"상태 코드\"가 추가적으로 들어갑니다",
"contributor": [],
"category": ["네트워크"]
},
"11": {
"quiz": "N+1 문제란 무엇이고 왜 발생하며 JPA에서는 어떻게 해결할 수 있을까요?",
"answer": "N+1 문제란 연관 관계를 가진 엔티티를 조회할 때 발생하는 문제입니다.\n\n해당 엔티티를 조회(1)했을 때, 해당 엔티티의 레코드 수 만큼 추가로 쿼리(N)를 날려야 하기 때문에 발생합니다. 이는 N+1번의 쿼리를 요청하게 되고 이는 심각한 성능 이슈를 유발합니다\n\n이를 해결하기 위해서는 기본적으로 모든 연관관계를 Lazy Loading으로 설정하고 연관 테이블이 필요할 때는 fetch join하는 방법으로 해결할 수 있습니다. fetch join은 관련된 레코드들을 한 번에 읽어오기 때문입니다. 혹은 EntityGraph기능을 사용해 해결할 수도 있습니다\n\nx대다 관계에서는 데이터 수가 불어나는 현상을 가지기 때문에 BatchSize를 추가로 적용해야 합니다\n\n출처 : 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화",
"contributor": [],
"category": ["Java", "데이터베이스"]
}
},
"frontend": {
"1": {
"quiz": "실행 컨텍스트에 대해 설명해 주세요",
"answer": "실행할 코드에 제공할 환경 정보(context)들을 모아놓은 객체를 말합니다.\n\nJS 엔진은 해당 컨텍스트와 관련된 코드 실행에 필요한 환경 정보들을 수집해 실행 컨텍스트에 저장합니다.\n\n실행 컨텍스트는 다음 3가지 프로퍼티를 가집니다.\n\nVariable Object : 선언된 변수, 함수들이 저장되는 객체입니다.\n\nScope Chain : 전역 객체부터 이어진 각 함수의 스코프 참조를 차례로 저장해 해당 함수가 참조할 수 있는 변수, 함수 선언 등의 정보를 담은 리스트입니다. 엔진은 스코프 체인을 통해 렉시컬 스코프를 파악합니다.\n\nthis value : 함수 호출 패턴에 의해 결정된 this 값이 할당됩니다.",
"contributor": ["aeong98"],
"category": ["JS"]
},
"2": {
"quiz": "호이스팅에 대해 설명해 주세요",
"answer": "인터프리터가 변수와 함수의 메모리 공간을 선언 전 미리 할당해 선언부를 코드의 최상단으로 끌어올리는 것(hoisting)을 의미합니다.\n\n이 때문에 선언하기 전의 변수임에도 불구하고 참조할 수 있는 현상이 발생합니다.",
"contributor": ["aeong98"],
"category": ["JS"]
},
"3": {
"quiz": "JS에서 this에 대해 설명해 주세요",
"answer": "this는 함수를 호출하는 객체에 대한 참조를 말하며, 어떻게 호출되었느냐에 따라 결정됩니다.\n\n전역 함수에서 호출되었다면 window 객체, 일반 / 내부 함수에서는 window 객체(strict mode라면 undefined), 객체 메서드에서는 해당 객체, 프로토 타입에서는 호출한 객체, 생성자 함수에서는 새로 생성된 객체를 참조합니다.\n\ncall, apply, bind 함수를 통해 this를 원하는 객체에 연결할 수 있습니다.",
"contributor": ["aeong98"],
"category": ["JS"]
},
"4": {
"quiz": "CSR과 SSR의 차이는 무엇인가요?",
"answer": "SSR(Server Side Rendering)은 서버가 클라이언트에게 서버 단에서 완전히 구성된 HTML 파일을 만들어 static한 웹 페이지를 제공하는 방법입니다\n장점 : SEO 최적화에 유리하며, 초기 로딩이 빠릅니다\n단점 : 매 페이지 요청마다 새로고침되기 떄문에 사용자 경험이 다소 떨어집니다\n\nCSR(Client Side Rendering)은 클라이언트에서 Ajax 등을 활용해 json과 같은 데이터를 fetching해 동적으로 HTML 문서를 만드는 방법입니다\n장점 : 클라이언트 액션이나 상황에 따라 동적 페이지 구현에 유리하며, 서버 부담이 적고 초기 로딩 이후 이동 / 상호작용이 빠릅니다\n단점 : SEO가 불리하며, 초기 로딩 속도가 느립니다\n",
"contributor": ["aeong98"],
"category": ["시스템 디자인"]
},
"5": {
"quiz": "이벤트 루프와 태스크 큐에 대해 설명해 주세요",
"answer": "V8과 같은 JS 엔진은 단일 콜스택을 사용하며 요청이 들어올 때마다 순차적으로 스택에 담아 처리합니다. 브라우저 혹은 Node.js는 태스크 큐를 사용해 이벤트를 핸들링하고, 이벤트 루프는 태스크 큐에 대기중인 함수를 콜스택으로 이동시킵니다.\n\n추가로 JS가 싱글 스레드라고 불리우는 이유는 콜스택과 이벤트 루프 동작 특성 상 하나의 코드가 실행되는 동안 다른 코드를 실행할 수 없다는 특징을 말하는 것이지, 스레드 하나에서 모든 작업을 수행하는 것은 아닙니다.",
"contributor": ["aeong98"],
"category": ["JS"]
},
"6": {
"quiz": "CORS가 무엇인지 말씀해 주세요",
"answer": "CORS(Cross-Origin Resource Sharing)는 교차 출처 리소스 공유라고 불리웁니다.\n\n브라우저는 \"동일 출처 원칙\"에 의거하여 API 요청 시 브라우저의 현재 주소와 API 주소의 도메인이 일치(Scheme, Host, Port)해야만 데이터로 접근할 수 있습니다. 만약 다른 도메인에서 API를 요청해 사용할 수 있게 하려면 서버에서 Access-Control-Allow-Origin 헤더에 대한 설정이 필요합니다.",
"contributor": ["aeong98"],
"category": ["네트워크"]
},
"7": {
"quiz": "브라우저 렌더링 과정에 대해 설명해 주세요",
"answer": "1. 브라우저는 HTML, CSS, JS와 같은 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받습니다.\n\n2. 브라우저 렌더링 엔진은 HTML, CSS를 파싱해 자료구조인 DOM, CSSDOM을 생성하고 이를 결합한 렌더 트리를 생성합니다.\n\n3. JS 엔진이 JS를 파싱해 AST를 생성하고 바이트 코드로 변환해 실행합니다. 이때 DOM API를 통해 DOM, CSSDOM 변경이 가능하며 변경된 자료구조는 렌더 트리로 결합됩니다.\n\n4. 렌더 트리를 기반으로 HTML 요소 레이아웃(위치와 크기)를 계산하고 브라우저 화면에 HTML 요소를 페인팅합니다.",
"contributor": ["aeong98"],
"category": ["네트워크"]
}
},
"tip": {
"1": {
"contents": "메모리는 디스크보다 읽기 성능이 10^5 ~ 10^6배 빠릅니다.",
"contributor": [],
"category": ["운영체제"]
},
"2": {
"contents": "java에서 배열을 복사하는 방법은 Object.clone()과 System.arraycopy 2가지 방법이 있습니다.\n\nclone()은 deep copy이나, 성능이 느립니다.\n\narraycopy()는 shallow copy이나 성능이 빠릅니다.",
"contributor": [],
"category": ["Java"]
},
"3": {
"contents": "Phantom Read란 주로 언두로그가 아닌 레코드를 읽을 때 발생합니다.\n\n레코드는 버전 컨트롤의 대상이 되지 못하기 때문에 다른 트랜잭션에서 언두 로그에 쓰기 잠금을 걸면 현재 트랜잭션은 당장 읽을 수 있는 실제 레코드에서 데이터를 읽어옵니다. 이는 다른 트랜잭션에서 변경했을 가능성이 있습니다.\n\n+) InnoDB의 Repeatable Read에서 Phantom Read가 발생하지 않는 이유는 Gap Lock을 지원하기 때문입니다.\n\nGap Lock은 읽은 레코드들 사이에 읽기 잠금을 걸기 때문에 다른 곳에서 쓰기 잠금을 걸지 못합니다.\n\n따라서 트랜잭션은 해당 레코드에 대해 같은 레코드 읽기를 보장 받습니다.",
"contributor": [],
"category": ["데이터베이스"]
},
"4": {
"contents": "JPA를 사용할 때는 엔티티를 직접 캐싱해선 안 됩니다. 영속성 컨텍스트가 관리하는 걸 캐시가 다시 관리하면 정합성 문제가 발생하기 때문에 DTO로 변환해 캐싱해야 합니다.\n\n참고 : 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화",
"contributor": [],
"category": ["Java"]
},
"5": {
"contents": "JPA에서 OSIV(OpenSessionInView)란, 트랜잭션 밖에서도 영속성 컨텍스트가 해당 엔티티를 관리하기 위해 DB 커넥션을 가지는 기능을 말합니다. OSIV가 켜져 있을 땐 커넥션이 마르기 쉽기 때문에 실시간 서비스에서는 해당 기능을 꺼놓고 프레젠테이션 계층으로 보내기 전 데이터를 모두 조회 후 내보내는 것이 좋습니다\n\n참고 : 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화",
"contributor": [],
"category": ["Java"]
},
"6": {
"contents": "SQL에서 AND로 연결된 경우에는 두 조건 중 하나라도 인덱스를 사용할 수 있으면 인덱스 스캔을 사용합니다. 그러나, OR의 경우 둘 중 하나라도 인덱스를 사용하지 못하면 풀 테이블 스캔합니다.",
"contributor": [],
"category": ["데이터베이스"]
},
"7": {
"contents": "CQS(Command Query Seperation) 패턴이란 모든 객체의 메서드를 쓰기 작업을 수행하는 \"command\"와 읽기 작업을 수행하는 \"query\"로 분리하는 패턴입니다.\n\n하나의 메서드는 command면서 query일 수 없으며, CQS를 지킬 시 부수효과가 일어나는 메서드를 분리할 수 있어 유지보수하기 쉬워지지만 간단한 코드도 복잡해질 수 있다는 단점을 가집니다.",
"contributor": [],
"category": ["시스템 디자인"]
},
"8": {
"contents": "집계함수 / GROUP BY / DISTINCT / SELECT 절 / 사용자 변수 / UNION을 포함하는 절 등에 해당하는 서브쿼리는 가능하면 외부 쿼리로 수동 병합하는 것이 성능 향상에 도움이 됩니다\n\n참고 : Real MySQL 8.0 1권",
"contributor": [],
"category": ["데이터베이스"]
},
"9": {
"contents": "인덱스를 활용한 정렬은 읽는 순간에 이미 정렬되어 있기 때문에 빠른 속도로 정렬할 수 있습니다. 이때 B-Tree 계열의 인덱스를 통해서만 정렬이 가능합니다.",
"contributor": [],
"category": ["데이터베이스"]
},
"10": {
"contents": "MySQL에선 GROUP BY에 사용된 조건은 인덱스 처리할 수 없어, HAVING 절 튜닝을 위한 인덱스를 고려할 필요는 없습니다\n\n참고 : Real MySQL 8.0 1권",
"contributor": [],
"category": ["데이터베이스"]
},
"11": {
"contents": "MySQL에서 정렬 작업을 수행하는 방식은 인덱스 정렬과 Filesort 2가지 방식이 있습니다.\n\n인덱스 정렬의 경우 이미 정렬된 상태로 레코드들을 읽어오기 때문에 성능이 빠릅니다. 이진 트리 검색만 하면 되니 O(logN) 성능을 보입니다.\n\nFilesort는 쿼리 실행 시점에 정렬을 수행해야 합니다. 따라서 정렬 과정인 O(NlogN) 작업이 추가로 필요합니다.\n\n참고 : Real MySQL 8.0 1권",
"contributor": [],
"category": ["데이터베이스"]
},
"12": {
"contents": "SELECT 쿼리를 날릴 때는 *이 아닌 꼭 필요한 칼럼을 직접 명시해 조회하는 것이 좋습니다. *를 사용할 경우 정렬 버퍼를 몇배에서 몇십 배까지 비효율적으로 사용할 가능성이 큽니다.\n\n또한, 임시 테이블이 필요한 쿼리에도 영향을 미칩니다.\n\n참고 : Real MySQL 8.0 1권",
"contributor": [],
"category": ["데이터베이스"]
},
"13": {
"contents": "SQL에서 LIMIT은 레코드를 일부만 가져올 수 있게 만들기 때문에 작업량을 줄여 성능이 향상됩니다.\n\n그러나 ORDER BY, GROUP BY 같은 작업은 조건에 만족하는 레코드 전부를 읽어와 버퍼에서 정렬 / 그루핑 작업을 수행한 후에야 LIMIT 작업을 할 수 있습니다.\n\n따라서 해당 작업들은 성능이 좋지 않을 수 있습니다.\n\n참고 : Real MySQL 8.0 1권",
"contributor": [],
"category": ["데이터베이스"]
}
}
}