-
Notifications
You must be signed in to change notification settings - Fork 10
/
0331.txt
260 lines (260 loc) · 16.6 KB
/
0331.txt
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
안녕하세요 포프입니다.
예전에 한 번 어떤 분이
함수형 프로그래밍에 대해 말해달라고 말씀하신 적이 있어요
그래서 목록에 적어두고 언젠가 말을 할 때가 되면 해야겠다고 생각을 했는데
생각해보니까 제가 함수형 프로그래밍에 대해 별로 아는게 없어요
그래서 설명할 수 있는게 없어서
그냥 오랫동안 얘기를 안 한 것 같은데
제가 함수형 프로그래밍을 써본 건 기껏해야 무슨
예전에 머신러닝 학교다닐 때 스칼라 좀 써서 이것저것 한 것들?
그런 부분이 사실 전부였죠
대충 어떤 건지 알고, 약간 써봤고
하지만 프로덕션 레벨에서 충분히 쓸 정도가 안되서
제가 그것가지고 뭐라 말하긴 그렇고
그냥 되게 많은 사람들이 궁금했던게 그거였던 것 같아요
함수형 언어가 함수형 프로그래밍(Functional Programming) 자체가
OOP를 대체할 수 있겠냐
저는
개인적인 생각으로는 아닐 거라고 봐요
그 대표적인 예가 뭐냐면
대표적인 예가 아니라 대표적인 이유가 뭐냐면
OOP를 제가 예전에 비디오에서 만들었듯이
OOP가 좋은건데, 너무 극단으로 가지 말자는 얘기를 했어요
사람이 이해할 수 있는 수준의 OOP
물체를 보고 아 이 물체는 이렇게 작동하는 구나
라는 수준에서 OOP는 아주 좋은 거지만
굉장히 구체적인 개념이 된 거였거든요 사실 옛날에 비해
근데 여기서 더 막 추가해서
우린 이런 재활용도 가능하고 추상화도 할 수 있고 그러면서 막
뭐라 그럴까, 새로운 개념에 너무 신나게 미친듯이 달려가면
결국에는 이해가 안되고 유지보수가 오히려 힘들어지는 코드가 나온다고 얘기를 했었거든요
제가 생각하는 oop의 가치는
사람이 생각하는, 물체에 대해 인지하는 그 사고방식을 그대로
프로그래밍 패러다임에 넣었다는게 가장 큰 장점인 것 같고
그렇기 때문에 전 oop가 사라질 거라고는 생각하지 않아요
오히려 oop가 주된 언어로 남을 것 같은데
이제 펑셔널(Functional, 함수형) 프로그래밍이 좀 더 유용해지는 부분이 있죠
그 유용해지는 부분들을 흔히 사람들이
멀티 스레딩에 펑셔널 프로그래밍이 좋다
라고 말씀을 많이 하셨어요
근데 최근에 트위터에서 제가 존경하는 영천님이 남겨주신 글을 봤었는데
이분이 사람들이 멀티스레딩 할 때 펑셔널 프로그래밍이 좋다고 하는데
성능상에서는 이게 어떻게 c보다 빠를 수가 있지? 왜 이걸 좋다 그러지?
라고 질문을 남겨주신 적이 있어서
제가 그거에 대한 답변을 단 적이 있거든요
제가 했던 답변은
되게 간단하게 말하면 뭐였냐면은
당연히 성능상으로는 C를 이길 수가 없다
아무리 멀티스레딩 뭐 하고 펑셔널 하던간에
다만 펑셔널 프로그래밍의 장점은
레이스 컨디션이 굉장히 적다 라는 거라고 말씀을 드렸어요
그래서 그 얘기를 조금 하려고 해요 말이 나온김에
일단 레이스 컨디션이 적다는 얘기가 뭐냐면
멀티스레딩 하시는 분들은 알겠지만
C에서 스레드를 여러개 띄워서 한 데이터를 접근하게 되면은
이 스레드에서 적는데 다른 스레드에서 적을 수도 있고
이 스레드에서 읽은 다음에 수를 하나 증가시켜서 넣는데
수를 넣기 전에 다른 스레드에서도 읽은 다음에 수를 하나 증가시켜서
덮어쓰게 되니까 수가 두가 증가되어야 할 게 하나가 증가되는 그런 문제들이 있잖아요
레이스 컨디션을 막기 위해서
뮤텍스 걸고 이러다가
아 이게 너무 느리다 그래서 아토믹을 걸었는데
어차피 아토믹도 어셈블리 레벨 내려가면은
결국에는. 뭐라고 그러지 그게
스토어 앤 로드(Load and Store)인가 그렇게 되어가지고 어차피 캐시 다 망가지고 이런 저런 문제가 있어서
그다지 빠르지 않은 CPU가 있었어요.
그래서 뭐든간에
그런 레이스 컨디션을 막기위해
락을 건다거나
락을 걸지 않더라도 아토믹을 쓰는 것에 대해서
성능 저하가 있을 수 밖에 없거든요
그런 부분이 있더라도
어쨌든간에 서로 락을 거는 기간이 적고
락을 무지막지하게 많이 걸지 않는다면
멀티스레딩이 빨라질 수 있고 그런 상황에서는 C가 훨씬 낫다는 건 맞아요.
펑셔널 프로그래밍이 재미있어지는게 뭐냐면
펑셔널프로그래밍에서는
모든 오퍼레이션 자체가 새로운 데이터셋을 주게 되어있어요
한마디로 내가 아까 얘기했던 것 처럼 같은 물체에다가
서로 뭐가 접근하고 그런 게 아니라
펑셔널 프로그래밍의 펑션은 물체를 받아놓고
거기에 새로운 물체를, 값이 변한 상태죠
바꾼거를 뽑아주는 방식이예요
어찌보면 이제
자바스크립트에서 리액트 같은게 그런 개념이잖아요
언제나 원웨이로 데이터가 흐르게 되어있는 경우가 있잖아요
리덕스였나 리액트였나 기억은 잘 안나는데
어쨌든간에, 나는 인풋이 있고 인풋을 받고나면 아웃풋을 줄거야
단, 인풋값은 내가 바꾸지 않고 새로운 값을 만들어서 전달해 줄거야 라는 개념이거든요
이런 식으로 실제
바꿀 수 없는 데이터를
프로그래밍에서는 임뮤터블이라 그래요
바꿀 수 있는 데이터는 뮤터블이고
바꿀 수 없는 데이터는 임뮤터블이라고 해요
모든 오퍼레이션을 임뮤터블하게 했기 때문에
여러 스레드가 많은 데이터를 건드려도
실제 이 나온 값, 한 펑션에서 나온 값은 그 펑션이 모든 책임을 진 거기 때문에
여기서는 레이스 컨디션이 없다는거죠
문제는 여러 스레드에서 여러 동일한 데이터를 가져가서 값을 만들다 보면은
똑같은 데이터 갖고와서 아까 말한 것 처럼 플러스 1씩 해서 뱉잖아요
그러면
이건 두개는 데이터 셋이예요
이거를 결과적으로는 합쳐갖고
합쳐야죠 플러스 1씩 된 것을
이게 하둡(Hadoop)이나 이런데서 보는 맵리듀스(MapReduce)라는 개념이 이런 개념이거든요
각 스레드나 각 머신이 각자의 오퍼레이션을 한 다음에
그 결과값을 모으고 모으고 모아서
최종값을 만들어낸다는 오퍼레이션이 되는거죠.
그래서 어쨌든 간에 이제
스레드가 많아지고, 스레드가 네개 다섯개일 때는 상관이 없는데 스레드가 몇백개가 되고
아니면 네트워크상에서 수백대의 머신으로 아까 말한 것 처럼 하둡처럼 맵 리듀스 같은 걸 해야 한다면
어쩔 수 없이 펑셔널 프로그래밍을 쓸 수 밖에 없어요.
수많은 스레드에서 한 데이터를 접근한다는 거 자체가 무모하기 때문에
그럴 경우에는 결과적으로 데이터를 임뮤터블로 만들어놔서
각각 레이스 컨디션 없는 상태에서 데이터를 만들고 리듀스 시키는 거죠
그래서 펑셔널 프로그래밍이 멀티스레드에 좋다는 얘기는
그런 레이스 컨디션이 없다는게 전부예요.
성능상으로는, CPU하나만으로의 성능상으로는 당연히 C같이
포인터로 접근해서 같이 셰어되어있는 데이터를 바꾸는게 빠른거고, 락을 걸더라도
그게 아니라 정말 엄청나게 많은 컴퓨터를 던져넣는 순간 부터는
하나하나당의 효율성은 아니고 전체 볼륨으로 볼 때
100대를 퍼부어서 30대 분량의 성능을 뽑아냈다
그래도 컴퓨터 한대로 뽑는 것 보다는 빠르니까
그런 개념으로 가면서부터 거기가 유리해지는거죠
그래서, 뭐라그럴까
사람들이 당연히 아 멀티스레딩은 펑셔널이죠 라고 말하는 순간부터 그거도 좀 문제가 있는 것 같고
멀티스레딩은 당연히 C다 라고 말하는 것도 문제가 있는 것 같고
자기가 쓸 수 있는 컴퓨터 환경과 자기가 하려는 오퍼레이션 같은 거
예를 들어서 저희가 무슨 게임을 만든다고 그러면
서버쪽에서 엄청난 머신러닝을 돌리는 방법도 있지만
그정도가 필요없는 게임이라면 보통 일반 클라이언트
유저의 컴퓨터에서 돌리는게 정상적이죠
서버비 문제가 있고
그러면 거기서 돌릴 수 있는 한계가 어디냐라고 생각을 한다면
당연히 아직도 펑셔널 프로그래밍보다는 C나 C++이 장점이 있는게 당연한거고
그게 아니라 아까 말했던 것 처럼 대용량 데이터를 맵 리듀스를 해야 한다면
당연히 펑셔널 프로그래밍이 훨씬 낫다고 말할 수 있고요
그래서 그 차이가 있는 거고
임뮤터블 뮤터블 이야기가 나왔으니까
러스트라는 언어에 대해서도 한번 얘길 해야 할 것 같아요
굉장히 많은 언어들이 기본적으로 변수를 선언을 하면
이게 언제나 뮤터블 이예요
내가 int A를 만들어 놨다면
여러 스레드에서 int A를 접근할 수가 있잖아요
그럼 그 값을 바꿀 수가 있어요
그렇기 때문에 싱글스레드에서는 상관이 없는데 멀티스레드로 가는 순간
기본적으로 예는 데이터가 바뀌는 타입이니까 모든게 레이스 컨디션에 노출이 되는 거죠.
그럼 이제 코드를 볼 때도
아 이게 변수인데, 과연 여기서 바뀔까 안바뀔까 이런 고민을 하는 거고
그래서 그런 경우에는
아 이게 안 바뀔 경우에는 앞에 const를 붙여서 임뮤터블로 만들어라는게 코딩 스탠다드로 나오고 있어요
근데 재미있는 건
러스트 같은 언어는 기본으로 모든 변수가 임뮤터블이예요
변수를 만드는 순간 예는 바꿀 수가 없는 변수고 바꾼다고 말하는 것도 이상하죠 그러면
그상황에서 니가 정말 예를 언젠가 값을 바꿔야 되는 애라고 확신한다면
그걸 뮤터블이라는 타입으로 새로 만들게 되어 있어요
mut 라는 키워드를 쓸텐데 기본동작은 모든 것이 임뮤터블이기 때문에
일단 아무생각없이 쓰면은 멀티 스레딩을 가더라도 크게 문제가 없고
단 니가 정말 이게 바뀌어야 하는 값이라고 생각을 한다면
뮤터블로 만든 다음에 그걸 나중에 다룰 때
니가 굉장히 뭐랄까 명시적으로 뮤터블로 지정을 해줬으니까
그만큼 신경을 쓰고 고민을 하고 그만큼 방어를 할 수 있다는 장점이 있죠
저는 러스트라는 언어가 처음 나왔을 때 굉장히 색달랐던게 그거였어요
아 기본으로 모든게 const 구나 그러면
사람들이 실수를 좀 덜하겠구나
내가 나서서 야 기본이 아닌애는 뮤터블로 바꿀거야 라고 말하는 순간
어 내가 뭔가 잘못하는게 있지 않을까
라는 고민을 하면서 코딩을 할 수 있다는거죠
그래서 러스트는
제가 제대로 써보지는 못했죠
옛날에 랭귀지스펙 나오는거 보고 아 정말 잘 만들었다 생각을 했고
포인터를 쓰려면 포인터를 쓸 수가 있어요
그리고 멀티 스레딩을 해서
데이터를 셰어할려면 할 수도 있는 걸로 알고 있어요
근데
기본적으로 컴파일 도중에 그런 걸 많이 잡아줄 수 있게 되어있어서
언어 자체가 좀 아까 말했듯이 약간 까탈스럽기 때문에
만약에 레이스 컨디션이 날 수 있는 코드를 짜는 순간 컴파일이 안 되는 순간도 있더라고요
그래서 되게 잘 만든 언어라는 생각이 들었고
그리고
그 언어의 장점 중 또 하나는 그거였던 것 같아요
그렇게 안전한데 정말 니가
포인터 뽑아 쓰고 이상한 짓 할려고 그러면
그것도 할 수 있어 다만 뭔가 특별한 키워드를 넣거나
특별한 구문을 써서 쓰라는 거죠
그럼 아까 제가 말했듯이
C 같은 경우는 막 포인터가 널려있고 열려있잖아요
쓰는 순간 아 터지면 터지겠구나
그런 생각도 안 하고 쓰거든
근데 러스트는 기본적으로 그게 안되게 되어있는 언어인데
니가 이런 새로운 걸 할려면 하나를 이걸 추가해서 해봐
단 이게 빠개지면 니 책임이야 그럼 사람들은 누구나 신경을 쓰게 되겠죠
C#에도 그런 똑같은 개념이 있었어요
지금도 있고, unsafe 라는 구문이 있죠
포인터를 정말 쓰고 싶으면 fixed 해서
unsafe를 쓰는 순간 실제 C에서 포인터를 쓰듯이 쓸 수가 있어요
unsafe operation 한 다음에 mem copy를 한다거나 이런게 다 가능한데
단 그거를 쓰는 순간 우리는 익셉션 체크도 잘 안해줄거고
깨지면 나는 몰라 라는거죠
그렇기 때문에 프로그래머가 정말 그런 성능을 높이기 위해서 특별한 이상한 연산을 해야 할 경우가 있다면 unsafe를 써서 하라는 거였죠
그래서 그런 부분이었고 러스트도 똑같은 개념으로 그런거고
C도 어찌 보면은 되게 비슷한 개념이 있었어요
다들 생각을 잘 못하는데
C가 되게 위험한 언어고 잘못 쓰면 펑펑 날라가는 언어이긴 한데
그거보다 더 엄청난 짓을 할 수 있었던 게 뭐냐면
C에서는 어셈블리를 쓸 수가 있잖아요
ASM을 쓰고 어셈블리 코드를 막 짜고
다음 컴파일 하면 어셈블리로 컴파일이 돼
근데 그 어셈블리에서 뻑나면 어떡할 건데요
C보다 더 디버깅 하기 어려워지고 그런 부분이 있는거죠
어셈블리를 하는 순간 이상한 짓을 완벽히 할 수가 있으니까
그래서 그런 개념에서
어찌보면 언어가 변천되어가는 과정일 수도 있고
옛날에는 어셈블리어 까지 코딩으로 다 짜야만 했던 정도의 시절이라면
C 정도만 짜도 상관이 없다, C++정도만 짜도 상관이 없다 라는 시대가 왔고
많은 사람들이 C++도 필요가 없다 포인터도 필요가 없다
그게 다 필요없는 세대가 올거다 라고 얘기 했는데
그 날은 오지 않았고 오지 않을거고
특정 분야에서는 그렇게 쓸 수 있어요 모든 분야에서는 그럴 수 없고
그렇기 때문에 C++을 대체하겠다고 용감하게 나온 언어들
러스트 같은 컴파일 언어들이
포인터 부분을 무시를 못하는거죠
어찌보면 C++을 처음에 만들던 언어
뭐라 그럴까 제작자들이
포인터를 못 없앤거에 대해 평생 후회를 했다는 이야기가 있거든요
저도 들은 얘긴데
그분들이 아마 포인터를 없앴더라면
C++이 지금 있지도 않을거예요
전 그렇게 생각해요
포인터 정도의 개념이 존재해야 하는 이유가 있고
그 개념을 계승을 하면서
새로운 컴파일 언어 좀 더 괜찮은 언어를 만들고 있는게 러스트라고 생각을 하고
문제는 러스트가 오픈소스고 모질라가 밀어주는 거라 파이어폭스 만드는
과연 언어가 발전은 하겠지만
툴이 얼마나 발전할지 걱정은 되지만
모르겠어요. 그날이 왔으면 좋겠는데
왠지 안 올거 같은 그런 느낌
그래서 오늘은 여기까지 세개에 걸쳐서 왔는데
함수형 프로그래밍 얘기를 하다가
한가지 했던 얘기가 OOP는 사라지지 않을거다 내가 볼 땐
함수형 프로그래밍이 쓰여야 될 곳이 있지만
OOP가 인간이 이해하기엔 가장 좋은 언어다 라고 얘기를 했고
두번째가 이제 함수형 언어가 멀티스레딩에 좋다는 얘기는
맞기도 하고 틀리기도 한 말?
예를 들어서 아까 말했던 것처럼 머신을 굉장히 여러대 돌리고
레이스 컨디션을 막아야 되는 그런 상황이 올 때는 함수형 프로그래밍이 굉장히 좋지만
순수히 멀티스레딩으로 속도를 최고 높일려는 방식
특히 컴퓨터 하나, 아니면 코어 개수가 그렇게 많지 않은 경우
그런 경우에는 C 계열의 언어와 데이터를 공유하고
동일한 데이터에 저장하는 패턴이 훨씬 빠르다는 얘기였고
세번째는 이제
러스트 언어를 기반으로 한 그런
뮤터블과 임뮤터블의 기본 방식의 전환 이랄까요 사고의 전환
그게 굉장히 좋고
어찌보면 이게
점점 프로그래밍이 복잡해 지면서
실수를 덜 할 수 있는 언어가 좋은 건데
C#보다도 훨씬 뛰어난 언어라고 저는 생각을 해요
그런 면에서 그래서
그 정도 얘기를 하면 될 것 같고
포프였습니다