우리는 프로그래밍을 공부를 대하는 자세를 돌아봐야 한다.
서두
프로그래밍이라는 것을 본격적으로 배우기 시작한 것은 대학에 입학하고 나서였다.
2018년도부터 시작했으니 어엿 4년이 되어가고 있다.
군대에서 지낸 기간을 제외하면 2년 남짓 되지 않는다.
그렇다고 나 스스로 돌아보기에 나의 실력은 과연 남들에게 자랑할 수 있을 정도인가? 라고 묻는다면 결코 아니다.
다만, 무엇을 배우고자 하는 부분에 있어 나는 이런 생각을 가지고 있다.
모르는 것을 공부하는 과정은 비가역적이다
배우고자 하는 것을 배우고 깨닳기 전의 전혀 알지 못하는 시점에서 무언가를 배울 때와
어느정도 시간이 흐르고 난뒤 알게 되었을 때 서로 시점을 이해하지 못한다는 것이다.
조금 더 풀어 쓰자면, 프로그래밍을 처음 배우는 입장과 가르치는 사람 간의 차이는 인지하기 힘든 격차가 있어서
가르치는 입장에서 말하는 것이 배우는 입장에서 듣는 것이 완전 다르다는 것이다.
알기 이전과 이후에 그 차이는 존재하지만,
왜 앎을 깨닳고 나서 그 이전의 상태인 모름을 이해하기 어렵다는 뜻이다.
당연한 말을 베베 꼬아서 말하는게 아니라,
우리가 보통 흔히 교육이라고 책을 집필하고, 강의를 할 때 기본적인 스탠스, 스탯의 차이를 모른채 교육을 한다는 의미다.
흔히 교육을 할 때 알고 가야할 중점을 징검다리처럼 만들어 입문자에게 차근 차근 따라오도록 이해시키려고 한다.
가르치는 입장에서 가지고 있는 사고의 흐름대로라면 너무나 당연할 수 있지만,
배우는 입장에서는 그 흐름, 개념 원리가 적용되는 나무 줄기 같은 맥락을 아직 만들지 못한 상태라서
책을 적절한 목차에 따라 집필하고, 강의를 한다고 따라올 것이라고 기대하는 것이 상당히 불친절하다는 의미다.
이미 해당 지식 분야에 대해서 사고 방식, 사고의 흐름이 익숙해진 분들은 자연스럽게 그 지식이 행동으로 내재화 되어 있다.
한 가지 분야의 일을 전문적으로 수십년간 해온 분들이 아무리 뛰어난 기술을 할지라도
몸에 내재화가 되어 있으면, 큰 수고를 들일 필요 없이 쉽게 쉽게 해낸다는 것이다.
우리가 A라는 업무를 새롭게 무언가를 배울 때 뇌가 활성화 되는 정도와
A업무 전문가가 A 업무를 수행했을 때 뇌가 활성화 되는 정도가 새로 배우는 사람보다 적은 것처럼
전문가는 적은 노력으로 기존의 A 업무의 프로세스와 해당 지식을 내재화,
즉 A 업무를 수행하는데 뇌를 사용하는 비용을 이미 최적화 시켜놓은 상태이기 때문에
새롭게 배우는 사람의 입장에서 최적화된 상태를 무지의 상태에서 따라가기란
교재에 주어진 핵심 요점 암기 말고는 없다는 뜻이다.
새롭게 배운다는 것은 활성화 되지 않은 뇌의 사용법을 새롭게 익히는 것으로 분명히 그에 수반하는
난관이나 오작동하는 경우가 있는데 이를 전문가의 수준에서 다시 헤아리기란 이미 어렵다는 말이다.
뇌의 입장에서는 이미 지식을 이해하는 고속도로를 만들었는데 왜 옛시절 아무것도 없는 험지를 달리냐고 생각할 것이다.
교육하는 자와 받는 자의 차이는 어디서부터 시작되는가
프로그래밍이 아니라 다른 주제에 관해서도 우리가 흔히 무언가를 배울 때
절대적인 지식과 인과관계에 대해서 그 맥락을 파악하고, 다른 예시나 사례에 대해서 직접 적용하는 과정을 거치고
습득한 지식의 인과관계를 내재화하는 것을 통해 배웠다, 안다라는 인지 상태를 가지게 된다.
절대적인 지식은 앞서 요약하자면, 이해는 안되더라도 일단은 외우고 시작할 수 밖에 없는 지식,
인과관계는 사고 과정, 뇌가 절대적인 지식을 조합하고 응용하는, 딥러닝에서 수 많은 파라미터들을 의미한다.
(1) 절대적인 지식이란
절대적인 지식은 패러다임, 즉 현대 과학 체계에 있어서 의문을 가지지 않는 ‘정의’와 같다.
현대의 과학철학라는 책에서 친절하게 설명한 내용처럼
절대 불변의 진리를 몇가지 담은 패러다임 위에서 우리는 파생되는 지식을 활용하고 또 아이러니하게 절대적인 지식으로 습득한다.
변증법적 사고처럼 여러 지식이 파생되어 소수의 절대적인 지식으로부터 우리는 수 많은 지식을 파생시켜왔다.
다시 프로그래밍으로 돌아오면, 프로그래밍에서 절대적인 지식이란 우리가 사용하는 프로그래밍 언어가 있다.
현대 프로그래밍의 패러다임을 구성하는 존재는 또 다시 계층으로 분리해 개념적인 측면에서 튜링 머신이 있고,
x86, ARM 아키텍처처럼 물리적으로 컴퓨터를 구현하는 설계 방법이 있다.
서로 호환되지 않는 측면에서 패러다임과 유사하지만, 여러개의 패러다임이 공존할 수 없는 일반적인 과학과 달리
컴퓨터는 여러 계층에 있어 각각의 패러다임이 호환적으로 존재할 수 있기 때문에 공존하는 특이한 모습을 볼 수 있다.
그래서 패러다임이라는 단어가 자연 과학계는 상호 베타적으로 작용하는 모습과 반대로
프로그래밍은 패러다임 이라는 단어가 원래 가지고 있는 베타적인 어감과 달리 융합과 재창조가 가능하듯이 쓰여야 한다는 점을 알고 있어야한다.
예를 들어
쓸만한 이미지가 없어 즉흥적으로 만듦!
객체지향주의(Obeject Oriented Programming),
함수지향주의(Functional Programming),
절차지향주의(Procedural Programming)이 있다.
위 3개의 프로그래밍 방법론을 ‘패러다임’이라고 부르기도 하지만, 베타적이지 않고 상호간 적절히 융합될 수도 있고 기호에 따라 선택될 수 있다는 특징이 있다.
또 다시 프로그래밍 언어로 접근하면 프로그래밍 언어로 프로그램을 작성할 때 언어의 한계로 인해
C언어의 경우 객체(Object)와 클래스(class)가 구현되어 있지 않아 절차지향적인 프로그램을 짜기 쉬워지는 특징이 있다.
다만 신기한 것은 절차지향주의의 대명사로 뽑히는 C 언어를 통해 만든 것이 Python이고, Python은 객체지향, 함수지향 프로그래밍을 모두 할 수 있다는 점이다.
마치 인류의 진화 단계에 있어 호모 에릭투스, 호모 사피엔스, 호모 사피엔스 사피엔스 모두 한 시대에 공존하는 것과 유사하다.
정리를 하자면
절대적인 지식이란 앞서 말했듯, 상호베타적이며 의문을 가지지 않는 불변하는 진리일 수도 있지만
소개해준 프로그래밍 방법론(객체, 함수, 절차 지향 프로그래밍)처럼 현재도 공존하고 있고 상호 호환이 가능할 수 있다는 것이다.
물론 원래 베타적인 의미를 가지는 ‘패러다임’이라는 단어를 가져다 쓴 선대 프로그래밍 학자들의 잘못도 있지만
사람이 사용하는 말과 언어는 시대에 따라 바뀌듯이 이러한 차이점이 있다는 점을 유의해주길 바란다.
절대적인 지식은 절대적이지 않을 수 있다!
당연하면서도 모두가 다 알고 있을 것 같은 보편적이고도 추상적인 지식일수록
섬세하고 자세히 써야되는 아이러니함이 있다.
이렇게 길게 쓴 이유는 화학계열을 전공하는 친구와 블록체인에 대해서 이야기를 나눌 때
언어, 정의에 대해서 명확하게 알고 시작하는 경향이 있어 유사하고 다양한 의미로 사용되는 컴퓨터 과학의 언어들이
가끔은 일관성이 없고 이름을 너무 못 지었다는 말을 들어본 적이 있었다.
나도 동의를 했고, 이게 마치 다른 나라 사람들이 한국어를 배울 때
띄어 쓰기, 높임말에 따른 어미 변화, 동음이의어, 많은 조사, 한자어, 단어의 변형, 헷갈리는 발음
(외국인이 한국어를 배우기 어려운 이유 중…)
수 많은 이유가 있지만, 우리는 의식하지 않아도 자유롭게 사용할 수 있는 것처럼
(서두에서 말한 전문가에 뇌 사용량 최적화 ; 고속도로 비유)
컴퓨터 세계에서도 같은 의미를 뜻하는 언어가 여러개, 또 비유적으로 쓰이다보니
이런 점에 있어서 프로그래밍을 가르치는 사람의 입장에서 입문자를 배려할 점이라고 본다.
객체, 인스턴스, 오브젝트 이 세 개의 단어가 수 많은 책에서 혼용되는 것을 보면 상당히 암울하다고 볼 수 있다.
(2) 배우고자 하는 인과관계란…
여기까지 우리가 무언가를 배울 때 필수적인 지식을 절대적인 지식을 모두 배웠다고 하자.
자 이제 그러면 지식간의 융합도 해보고 어떻게 작용하는지 공부하게 될 것이다.
앞서 언급한 딥러닝의 비유를 다시 가져온다면 인과관계란 파라미터를 의미한다.
딥러닝에 대해서 아시는 분들이라면 저 파라미터들은 사람들이 직접 조정하는게 아니다.
이미 존재하는 알고리즘을 기반으로 수치를 재조정해서 근삿값까지 가는 과정에서 조정이 된다.
애초에 딥러닝이 사람의 신경을 기반으로 역설계를 통해 만들어졌기 때문에 이런 유사성을 띄는 것이 당연할 수도 있다.
이미 존재하는 알고리즘은 사람이 살면서 그동안 배운 지식과 경험을 토대로 얻은 사고방식이라 보면 되겠다.
그래서 이미 다 배우고 익숙해진 사람이 처음 배우는 사람에게 무언가를 가르칠 때
파라미터를 직접 일일히 손으로 조정할 수 없고,
수 많은 학습 데이터를 돌리듯이 교육을 통해 파라미터가 최적해를 찾는 것이 일반적이고 보편적인 배움이라고 볼 수 있다.
딥러닝을 처음 시작할 때 파라미터들은 모두 랜덤한 값을 시작으로 학습을 시작한다.
마치 우리가 만나는 사람들이 살아온 인생이 모두 다르고, 알 수 없는 것처럼 말이다.
그래서 그 최적해를 찾는 속도가 각각 다를 수도 있고, 우리가 학습을 통해서 얻고자하는
손실함수의 전역 최소해(global minimum)를 찾지 못하고 지역 최소해(local minimum)에 빠져
원하는 학습 결과를 얻어 내지 못 할수도 있다.
딥러닝에 다양한 학습률(학습 방법)과 마찬가지로 사람이 어떻게 배우느냐에 따라서
배웠다라는 결과물이 나오기까지 수 많은 시가노가 노력이 필요한 모습이
딥러닝이 사람의 뉴런을 모방해 만든 것이지만, 학습 방법으로도 비유를 할 수 있는 것 같아 신기하다.
딥러닝이 항상 100% 정답을 내지 못하고, 최소해가 있는 것처럼 사람의 학습과정에 있어 유사해 재밌기도 하다.
프로그래밍에 대입해서 설명을 해보자
기능을 구현하기 위해 A, B, C를 하고, D를 최종적으로 하면 된다라는 예시를 배운다는 과정에 비유를 해보자.
아주 단순하게 그림으로 표현하면 다음과 같다.
A, B, C, D로 추상적으로 예시를 들었지만 비유를 들자면 순차적인 과정의 대표로 ‘요리’가 있다.
요리도 놓고 보면 식재료를 모두 갖춰 준다고 해도 순서를 지키거나 방법을 몰라서
계속해서 설명서와 후라이팬을 번갈아 보는 자신의 모습을 한번 쯤 봤을 것이다.
아무튼, 다시 A, B, C로 설명을 이어가자면
사람들은 아무리 단순한 절차 과정임에도 불구하고 이런 식으로 이해를 하게 된다.
요리야 불이 있고 물이 튀느라 정신이 없어 당황한다고 할 수 있지만,
앉아서 직접 공부하는 내용임에도 불구하고 이상한 인과관계를 통해 사고를 하는 과정이 있다.
이런 절차는 프로그래밍을 하는 도중 문제를 마딱드렸을 때 질문하는 과정에서도 쓰여야한다.
이렇게 사고의 절차를 나열해 놓고, 이 절차를 위의 다이어그램처럼 제 3자 입장에서 놓고 봤을 때
질문을 하기 전에 왜 틀렸는지 알 수도 있고,
또 어떻게 내가 이런 사고 과정을 거쳤는지 (왜 그렇게 생각을 했는지 & 이 결과가 어떤 이유로 나왔다고 생각했는지)
어떻게 질문을 할 수 있는지 (절차 도중에 어떤 점이 잘못되었는지, 어떤 것을 물어볼지)
스스로 배울 수 있기 때문에 중요하다.
이런 과정은 하나의 큰 문제를 작은 절차로 나뉘어 작은 단위로 문제를 해결하는
알고리즘의 분할정복과 같은 흐름이다.
이 예시로 비유를 들자면 이런 식의 대화, 사고의 흐름이 있어야 한다.
이런식으로 이상적인 흐름이 나오게 된다(희망 사항).
이렇게 자신의 풀이 과정, 문제 해결 과정을 모듈화 하고 단계별로 나누는 것이 문제를 파악하는데 쉽고
질문을 잘 할 수 있어 이 과정이 상당히 중요하다.
대학교 1 학년 과정에서 객체지향 프로그래밍 수업이 모든 대학에서 그러지 않겠지만,
단순히 객체를 과자를 찍어내는 틀이라는 아주 -같은 비유를 들고 설명을 끝내버리니 참으로 비통한 심정이다.
문제를 절차적으로 이해하는 과정에 앞서
문제 상황(코드)을 만들 때부터 아주 좋은 방법이 있다.
그것은 객체지향적인 프로그래밍을 하는 것이다.
알고리즘이 성인을 위한 수능으로 변질되어 가는 과정 속에서 abstract class와 interface를 사용하는 용도나 의도를 모른채
알고리즘 스터디를 하는 모습을 보면, 프로그래밍의 근간을 위태롭게 만드는 것이라고 생각한다.
개 같은 코드로 고생을 하고, 개 같은 코드 때문에 협업 소프트웨어가 만드는 시장의 크기는
돈을 주고 알고리즘을 만드는 사회적 비용보다 훨신 크다.
(여기서 말하는 알고리즘은 AI 알고리즘이 아니라 취업 할 떄보는 수준의 알고리즘을 의미한다)
개 같은 코드로 인해 유지보수가 힘들고 그런 것들은 수 없이 당하면서,
객체지향적인 프로그래밍을 이렇게 찬밥 취급을하니 가르칠 수 없다고 생각하는 분야인건가?
이건 마치 기초 과학을 무시하고, 응용과학을 집중적으로 투자하는 모습과 유사하다고 볼 수 있다.
컴퓨터가 과거와 달리 소수의 과학자들만이 사용하는 전유물이 아니다보니 전체적인 수준이 하향평준화 되었다고 볼 수 있지만,
프로그래밍만큼 종사자의 학력이나 나이의 폭이 넓고, 취업까지 소요되는 시간이 짧은 업종이 보여주는 단면의 결과물이 아닐까?
앎을 안다는 것
고등학생일 때, 학교 근처의 국어학원 선생님이 있었는데 그 당시 아직도 기억에 남는 말이 있다.
내가 글을 읽을 때 어떤 생각을 해서 읽고, 쉽게 이해하는 거지?
당시에는 크게 감흥을 느끼지 못했지만, 아직도 이 말이 기억에 남았다.
당시에 어떤 큰 의미를 파악한 것은 아니였지만, 이 짧은 한 마디가 내 깊은 무의식 속
메타인지를 ‘탁’하고 밝힌 것 같다.
무언가 새로 배울 때 배우는 학생의 입장으로서 해야 할 것들
우리가 무언가를 새로 배울 때,
우리가 가지고 있는 보편적 지식으로 새로운 분야의 지식을 받아 들이는데 적용하고 검증하는 과정을 거친다.
그렇게 점차 우리는 예시처럼 구체적인 사례를 기반으로 반복된 패턴을 인지하고
수학의 수식처럼 추상화 과정을 거쳐, 구체적인 사례가 아니여도 적용할 수 있는
추상적 지식, 즉 ‘이론’을 내재화하게 된다.
앞서 “배우고자 하는 인과관계란” 목차에서 예시를 든 것처럼
우리는 무언가를 새로 배울 때 한 치 앞을 모르고, 손을 더듬는 입장과 같다.
그러나 추상적인 지식을 알게되었을 때 더듬을 필요 없이, 직관적으로 이해하기 시작한다.
모든 배우는 이가 가져야 하는 의무는,
배우기까지 우리는 어떻게 손을 더듬었는지,
배우기 전까지는 ‘당연히 그러는 거 아니야?’라는 생각을 왜, 어떻게 했는지
초심자의 입장에서 어떤 사고의 흐름이 이어졌는지를 기록하고,
이를 조정해 줄 수 있도록 남긴 기록(이정표)을 통해 교육자의 입장에서 다시 봤을 때,
사고의 흐름 속 이정표를 다시 돌아봐 초심자의 사고 흐름을 파악할 줄 알아야 한다는 것이다.
이는 교육하는 사람과 교육을 받는 사람 양쪽의 입장 모두 노력해야하는 부분이다.
반복된 노동, 코드 그리고 관례 같은 행위는 단순한 반복을 통해 이해할 수 있지만,
그 과정을 관통하는 추상적인 지식을 뽑아 내고, 전수하는 것이 교육이자 남겨야할 기록이다.
우리는 메타인지를 하고 있었지만, 메타인지라는 단어를 몰랐을 뿐 이전에도 시행되고 있었다.