-
Notifications
You must be signed in to change notification settings - Fork 10
/
0557.txt
11 lines (6 loc) · 12.7 KB
/
0557.txt
1
2
3
4
5
6
7
8
9
10
11
안녕하세요 포프입니다. 오늘 제목은 조금 어그로를 끌 수도 있는 것 같은데 이 표현이 잘못 사용되고 있는 경우들이 좀 있어서 그거에 대한 비판으로 어그로 제목을 단 겁니다. 그래서 제가 '섣부른 최적화를 해라'라고 하는 건 아니에요. 섣부른 최적화는 안 하는 게 맞습니다. 맞는데요... 섣부르다는 판단을 우리가 하는 거잖아요? 우리 프로그래머가 그 판단을 제대로 안 한채 사실에 근거해서 하지 않고 그냥 자기 방어수단으로 '그거는 섣부른 최적화니까 안 할 거야' 하지만 뒷머리 속에선 '하지만 나는 그걸 할 실력도 없고 나는 올바른 코딩 Practice가 뭔지도 몰라...' 이렇게 말하시는 분들을... 그냥 그런 분들이 있어서 그분들 어차피 제 비디오 안 볼 거니까 그런 말에 현혹되지 마시라고 만드는 비디오입니다. 알았죠?
요게 사실은 제가 언제나 해왔던 말이기는 합니다. 일단은 섣부른 최적화가 하지 말라는 의미가 뭔지부터 말씀을 드리는 게 좋을 것 같아요 자꾸 오해하실 수 있으니까. 무슨 의미냐면은 저희가 코드를 작성을 해요. 그럼 코드가 어느 순간 느리게 돈다. 굉장히 효율성이 안 나온다. 그럴 때 보통 프로파일을 해 보거든요? 프로파일 도구들이 좋은 게 많기 때문에 비주얼 스튜디오 굉장히 좋습니다. 그러면 프로파일을 보면은 어느 특정 부분, 어느 특정 함수가 느리다 라는 게 보통 나와요. 그래서 그게 일반적으로 내 프로그램 작성하면은 그 느린 부분은 한 10% 정도도 잘 안 돼요. 그 10%만 고치면은 게임이 15 프레임으로 돌던 게임이 60 프레임이 될 수도 있는 겁니다. 그리고 그게 아무리 많더라도 내가 작성한 코드에 20%를 넘어가는 경우는 저는 거의 못 봤어요. 제가 최적화 때문에 여기저기 끌려가서 남들이 일 벌여 놓은 거 뒷수습하고 이런 일을 되게 많이 했거든요? 근데 최적화 아무리 해봐야 정말 말 그대로 느린 부분은 굉장히 적어요. 그래서 섣부른 최적화를 하지 말라는 얘기는 프로그래머는 괜히 내가 뭔가를 최적화 기법을 알고 있다는 생각 때문에 코드를 작성할 때 쓸데없이 이걸 최적화하려고 하는 경향이 있어요. 근데 코드에서 제일 중요한 것은 나중에 내가 6개월 뒤에 그 코드를 봤을 때 뭐 하는지 한 번에 이해할 수 있는 거 그리고 내 동료들이 그 코드를 봤을 때 뭐 하는 건지 이해할 수 있는 거... 그래야 지만 버그가 있을 때 버그를 고치려다가 봐도 한눈에 보이고 누군가 기능을 추가할 때도 쉽게 추가할 수 있으니까... 그래서 제품을 만들 때 제일 중요한 것은 협업하는 사람끼리의 서로 공통적으로 쉽게 이해할 수 있는 코드가 있어야 된다는 거거든요. 근데 최적한답시고 그걸 깨시는 분들이 있습니다. 그러지 말라는 거예요. 그래 봐야 이 제품 속도 개미 눈곱만큼도 안 빨라져야 하는 얘기입니다. 그래서 그럴 때 섣부른 최적화를 하지 말라는 거예요. 그리고 최적화를 할 때는 기본적으로 측정을 해보고 어디가 느린지 그리고 측정이 한번 할 때 느릴 수 있으니까 한번 더 측정을 해보고 그다음에 느린 부분을 고치고 또 측정을 한 두 번쯤 해서 빨라지는 걸 확인했을 때 최적화가 된다고 얘기하는 겁니다. 그게 섣부른 최적화를 하지 말라는 것에 의미 그리고 최적화를 하는 방법이에요.
근데 여기서 약간 재미난 패턴들이 생겨납니다. 이 섣부른 최적화를 하지 말라는 말은 굉장히 오래전에 나온 얘기고 되게 유명하신 분이 했을 거예요 제 기억으로는. 근데 그 이후에 실력도 없는 프로그래머들이 누군가가 "이거는 이렇게 하는 게 좋다"라고 말할 때 "아 이건 섣부른 최적화예요. 그걸 왜 해요?"라는 식으로 "그건 나쁜 거라고 했어요" 그러면서 약간 곡해해서 사용하는 경우들이 있었어요.이거는 C++에 특화된 얘기인 것 같기도 한데 그리고 제가 이 얘기하면 분명히 그거 아무 차이 없어라고 거품 물고 뛰어 오실 분도 있을 거예요. 근데 제가 하고자 하는 말은 뭐냐면 내가 코드를 작성을 해요. A라는 코드와 B라는 코드를 작성할 수 있어요. 그리고 얘는 언제나 반복되는 패턴이에요 어느 경우에나 그 경우에 내가 A라고 작성을 했을 때 B보다 속도가 느릴 수 있어요. 단 이 함수가 많이 호출되는 함수가 아니라면 제품이 영향을 미치진 않지만 진짜 CPU 한 사이클에도 느려지는 그런 함수가 게임 한 프레임일 때 게임 한 프레임이 60 프레임이라면 1초를 60으로 나눈 거 30 프레임은 1초를 30으로 나눈 거 안에 한 번에 그려야 되죠? 그 안에 그 함수가 몇 만 번 5~6만 번 호출되는 경우들도 있어요. 거기에 이 느린 코드가 있으면 CPU 사이클 한 사이클 느려지는 게 5~6만 사이클로 늘어날 수도 있다는 거예요. 그러면 A 하고 B라는 코드가 동일하게 가독성은 좋아요. 작성하는 방법이 다른 거예요. 최종 결과도 똑같아요. 그렇다면은 프로그래머인 우리는 습관을 무조건 빠르고 좋은 쪽으로 들여놓는 게 좋습니다. 무조건 B로 왜? A도 웬만한 경우에 문제가 안돼요. B도 문제가 안 돼요. 근데 99%의 확률로 어쨌든 간에 아주 개미 눈곱만큼이라도 B가 빨라요. 가독성이 똑같아요. 근데 B라는 방식이 어디 쓰일지 모르기 때문에 습관을 잘 들여놓는 게 좋다는 거예요. 그러면 습관을 잘 들여놓는 것만으로 내가 작성하는 코드에서 나중에 뛰어 들어가서 최적할 일이 적다는 거죠.
근데 습관을 잘 들이고 그냥 '이렇게 하면 잘 돼'라고 믿고 습관 들여서 작성하면 되는데 괜히 섣부르게 비관적이 되는 사람도 있다는 거예요. Premature Pessimization 실제 용어를 만드신 분이 있고 그 그분이 만들어서 책을 썼는지는 모르겠지만 그게 인용되어 있는 책도 있습니다. 그게 저번 편에서 제가 말씀드렸던 C++ Coding Standards: 101 Rules라는 책인데 제가 링크는 걸어 드릴게요. 거기에 그분이 그런 얘기를 해요. 이분은 참고로 저자 중에 한 분은 굉장히 유명한 분이에요. 마소에서 C++ 쪽을 굉장히 많이 입고 계시는 분이기도 합니다. 그래서 그분이 든 예가 뭐냐? 제가 예전에도 라이브를 통해서 했던 얘기기도 해요. 자 1번 i++ vs ++i 참고로 학교 다닐 때는 다들 i++습니다. 이 2개가 똑같이 동작하는 경우에 제일 좋은 예는 for문에서 증감할 때죠. 하지만 저는 어떤 사람의 글을 읽고 ++i로 습관을 확 고쳐버렸습니다. 그래서 저는 더 이상 i++ 않아요. 이렇게 얘기하면은 i++가 ++i 보다 느린가요? 물어요. 개미 눈곱만큼 느립니다. 하지만 아까 말했듯이 그게 여러 번 호출이 되면 그게 쌓여서 더 느릴 수가 있어요.똑같은데 왜 굳이 i++쓰냐고요... 가독성이 똑같은데. 그럼 ++i를 쓰는 게 맞거든요. 그리고 단순히 int에 i++/++i 부분도 있지만 추가적으로 C++에서 코드를 작성하는 사람들의 일반적인 습관 업계의 정착된 어느 정도의 관습에 따르면 내가 어떤 커스텀 클래스를 만들어요. 거기에 operator를 오버 로딩해서 i++처럼 후위 증감을 만들고 전위 증감 연산자를 둘 다 만들어요. 그러면 일반적으로 전위 증감 연산자에 필요한 로직을 다 넣고 후위 증감 연산자에서는 전위 증감 연산자를 호출하는 방식으로 코드를 작성합니다. 코드 중복을 막기 위해서 그래서 이런 경우에는 커스텀 클래스에 들어가면 어쨌든 간에 전위(pre)로 하는 게 곧바로 함수 한번 호출해도 되는 거고 후위(post)로 호출하는 것은 함수 두 번을 호출하게 됩니다. 최적화에서 당연히 그걸 없애줄 수 있지만... 그렇기 때문에 습관 자체는 무조건 전위 증감으로 코드를 쓰는 습관을 들여두는 것이 동작이 똑같은 코드라면 결과적으로는 무조건 빨라지는 방법입니다. 그리고 그거는 섣부른 최적화라고 얘기할 수가 없어요. 그걸로 인해서 가독성이 깨지는 것도 아니고 코드를 짜기 어려워지는 것도 아니고 드는 노력은 거의 똑같아요. 그래서 그게 그 책에 예로 들어가 있어요. 그게 한 가지 예... 말 되죠? 그리고 그 책에서 몇 가지 더 예를 드는 것들이 당연히 있어요. 그거는 뭐 궁금하시면 보시면 될 것 같은데 제가 지금 생각나는 게 또 하나 있는지 볼게요. 제가 그거 그 책에 나오지 않은 거를 뭔가 말하면 좋은 게 있겠다라고 생각한 것도 사실은 있기는 해요.근데 잘 기억은 안 나네요. 제 생각에는 그 책에서 말했던 게 또 하나가 저런 게 있었을 것 같아요. 말을 안 했으면 이것도 중요한 습관 중에 하나고 Pass By Value(값에 의한 전달)냐 아니면 Pass By Reference(참조에 의한 전달)냐 어떤 자료형의 데이터가 커지기 시작하면 기본적으로 const 레퍼런스를 전달하는 게 일반적인 관습입니다. 근데 const를 빼먹는다거나 레퍼런스 안에서 복사를 일으키는 사람들이 있어요. 물론 그 클래스가 굉장히 작으면 복사가 차라리 빠릅니다. 근데 그게 16바이트 정도 기준으로 그게 아마 바뀔 거예요. 그리고 일반적인 클래스는 보통 16바이트 넘거든요? 그래서 어떤 클래스를 매개변수로 전달할 때는 예전 같은 경우에 포인트로 전달했겠지만 C++에서는 참조로 전달을 하고 그리고 참조로 전달한 게 원본을 전달하니까 바뀌면 안 되니까 그걸 막기 위해 const를 넣는 습관을 거의 하거든요? 그래서 const 레퍼런스 습관이 안 들어있다? 그럼 이거는 어느 순간 버그를 만들거나 추가적으로 누가 기능을 추가해서 뭐가 고치려고 할 때 문제가 생기는 그런 일들이 생기는 거기 때문에 이것도 const를 넣고 하면 최적화를 좀 더 잘해주기도 해요. 컴파일러가 할 수 있는 부분들이 있어요. 그래서 이게 섣부른 최적화라고 말하기보다는 섣부른 비관화를 막는 방식이죠.
그리고 세 번째는 이거는 POCU 아카데미 COMP3200 과목에서 열심히 제가 얘기하고 시험에서 이렇게 하면 무조건 점수 깎아버리는 방식인데 클래스 생성자에서 초기화 리스트를 안 쓰고 assignment(과제)를 수행하는 경우 이것도 쓸데없이 느려지는 과정 중에 하나입니다. 그리고 그래야 될 이유도 없고요. 그리고 잘못하는 순간 나중에 뭔가 이상한 일이 일어나기도 합니다 사실은. 굉장히 이거는 흔히 일어나지 않는 일인데 그래서 그거를 하지 않는 것도 이제 습관을 제대로 안 들여놓고 이게 왜 그런 건지 제대로 이해 못 한 채 그냥 비관적에 빠져서 '그런 거 상관없어... 이렇게 똑같아... 그거 배워서 뭐해... 이런 거다'라고 그 사람은 얘기를 하고 있습니다. 그래서 "이게 뭐 똑같잖아요? 어차피 같잖아요?"라고 하면 "똑같으면 나은 방법으로 해"라고 말하는 게 일반적인 예고 "그걸 모르면 습관을 들여"라는 겁니다.이거는 어느 분야나 똑같잖아요? 습관만 잘 들여두면은 그냥 손에서 그냥 나오는 거거든. 그 습관을 왜 굳이 안 바꾸는지는 모르겠지만 '뭐 그냥 바꿔봐야 소용없어'라는 비관적인 마인드가 그런 거겠죠. 그래서 그런 얘기들을 설명드렸고요. 그래서 제목이 어그로였지만... 그래서 섣부른 최적화를 하지 않는 건 좋은 거지만 그거를 섣부르다는 그 핑계를 대면서 내가 모르고 있는 아니면 누가 알려줬는데도 내가 학습을 못한 그런 부분에 대한 실드를 치지 말자 그냥 조용히 혼자 넘어가세요 그걸 안 하고 싶으면. 괜히 그런 얘기 하셔 갖고 다른 사람들 특히 새로 오시는 주니어면 넘어갈 수 있거든요? '필요 없는 거구나' 나중에 보면 굉장히 필요한 거거든요.
그래서 그런 것들 우리 신경 좀 쓰고 삽시다 그렇습니다. 섣부른 최적화도 하지 마시고 그것보다 더 나쁜 것은 섣부른 비관화 그게 더 나쁩니다. 포프였습니다