알고리즘 공부, 2018 목표 생각.

인터뷰 준비가 시작된 이후로 조금씩 알고리즘을 공부해 왔었다.

가장 파고싶었던 것은 사실 언제 산지도 기억나지 않는 Introduction to Algorithms이다. 언젠가 봐야지 하고 아마 2009년쯤에 구매했던 것으로 기억하는데, 한 1년 정도는 심지어 비닐도 뜯지 않았다. 학교에서 교재로 쓰이지도 않고, 시간을 내지 않으면 공부할 일이 없어서 먼지만 쌓아두고 있었다. 도전을 안해본 것은 아니지만, 영어 원서를 자유자재로 읽지 못하는 스무살의 내게는 벅찬 교재였다.

이 책을 지난 11월부터 보기 시작했다. 원래 학부때 자료구조 교재로 쓰던 Fundamentals of Data Structure in C 를 보긴 했는데, 책이 상당히 좋지만 약간은 어려웠다. 물론 서술형식으로 쓰여있음에도 나름 방대한 데이터 구조를 다루기 때문에 그랬던 느낌이기도 하고, 인강 같은게 없어서 혼자 따라하기에 더 어려웠던 것 같다. 그런데 Introduction to Algorithms는 일단 MIT Courseware강의가 있고, 강의 내용을 들어보니 아주 깊이있게까지 들어가지는 않지만, 책의 의도와 비슷하게 일단 ‘기본’에 충실하는 내용이다. 덕분에 한달좀 넘게 공부하였음에도, 그간 러프한 개념만 알고 살았던 (…) Heap이나 이를 활용한 Priority Queue, 그간 어렵다고(?) 기피해온 Merge Sort, 힙소트, AVL 트리, 다이나믹 프로그래밍 등에 대해 책을 따라읽고 강의를 들으며 이해했다.

확실히 이 책 자체를 전부 다 볼 필요는 없었다. 총 35 챕터 중에 NP나 Selected Topic을 제외한 24개의 챕터만 봐도 무방하다. 나는 지금까지 16개 챕터를 봤는데, 사실 이중에서도 건너띈 것이 상당수 있다. 예컨데 Strassen’s Matrix Multiplication 같은것. 일차적으로 MIT 강의에 없는 부분은 건너띄었고, 몇 번을 봐도 이해가 안되거나 복잡한 챕터는 나중에 보기 위해 건너띄었다.

24개의 인강 중에 7개 강의를 들었는데, 강의 하나에 한시간이라서 조금은 시간이 걸리곤 한다. 거기다 24개 강의와 추가로 phd과정 학생이 보완 설명하는 강의(Recitation)가 추가로 존재한다. 이 또한 24개가 있어서 사실 좀 부담이지만 듣다 보면 질답이 꽤 많기 때문에 이를 건너띈다면 꽤나 할만하다고 생각한다. 실제로 책에서 Recursion Tree가 도무지 이해가 안갔는데, 보완 설명을 듣고 나서 어느정도 이해가 가기 시작했다.

이제 남은 부분은 DP를 좀 더 공부하고, 그래프와 나머지 알고리즘 들인데 사실 그래프는 오래전 중학교 시절 그나마 가장 즐겁게 공부하던 부분이라 아직은 건들지 않고 있다. DP는 최근에야 관심이 증대했는데 개인적으로 순차적으로 공부하는걸 좋아해서 아직은 처음부터 쭉 훑고 있는 편이다. 학교나 회사일 등으로 지금까지는 사실 제대로 집중하지 못했는데, 조금씩 시간을 더 낸다면 내년 초에는 완강할 수 있지 않을까 라는 기대를 하고 있다.

이 책과 더불어 엊그제부터 Coursera의 Algorithms, Part I 을 듣기 시작했다. 처음 나오는 Union Find를 들으며, 아니 별다른 알고리즘과 관련된 이론 없이도 이렇게 알고리즘에 대한 필요성을 인식할 수 있다니, 그리고 관련된 문제들을 보면서 왜 실제 실무에서 이런 알고리즘을 만들어 가는 사고가 필요한지 이제야 이해가 가기 시작했다. 과제가 아직까진 조금 난감하긴 하지만, 노력하면 스스로 충분히 풀 수 있다는 느낌을 받는다.

이 두 개의 강의를 보면서 느낀점은, 일단 강의의 수준이 상당하다는 점이다. 지난 글에도 언급했지만, 미국 대학원을 졸업하니 그나마 영어가 들리기 시작해서 강의가 이해되기 시작했다. 결국 내가 대학원에서 들었던 강의들과 구성은 아주 크게 다르지 않다. 교수는 이해시키려고 노력하고, 저마다의 스타일이 있는 편이다. MIT학생이라 해도 강의 자체에 있는 학생들은 학부생이고 (물론 머리가 좋겠지만.) 내가 알고리즘을 듣던 2012년을 생각해 보면, 혹은 강의에서 보이는 학생들의 수준을 생각해보면 지금 내 수준이 그나마 저정도까지는 올라왔다는 느낌을 받는다. 즉, 이해가 된다는 점이다. 이게 원서나 영어 강의가 들려서 그런것일수도 있겠지만 졸업 후 마음의 여유가 한층 높아지니 내게 부족한 것도 보이고, 정리할 수 있는 시간도 생겨서 그렇지 않을까.

학부때 나름 알고리즘이나 AI교수님이 유명한 분이셨는데, 하필 내가 들을 때에 안식년이셔서 강사에게 수강했고, 그 부족한 부분은 지금까지도 내게 큰 공백으로 자리잡아왔다. 언젠가는 공부해야지 해야지 하던 것이 벌써 5년이 지났다. 지금까지는 시간이 나면 모던 웹과 함수평 플밍, 아키텍처 등에 대해 공부해왔지만 알고리즘은 결국 프로그래머의 가장 기초가 아니였던가, 하면서 나는 선듯 공부할 엄두를 내지 못했다. 사실 개발을 할 때에 알고리즘을 알고 모르는 것이 개발에 지장을 주지는 않았다. 무한정의 메모리, 무한정의 CPU라고 생각하고 프로그래밍을 했고, 풀이 가득 차거나 utilization이나 threshold가 가득 차면 그때서야 부랴부랴 병목점을 찾고 해결하거나 scale-up을 하거나 refactoring을 해왔으니 말이다.

미국에 오니 확연히 느끼는 점이, 컴퓨터 공학을 진실되게 전공하지 않으면 결국 흔히 말하는 코더로써 전락할 수 밖에 없다는 사실이다. 아무리 폭넓게 안다해도 최소한 CS에서의 기본 학문은 심도있게 알고있어야 그게 기반이 되어서 비전공자와의 차이점을 만들어 내는 것이다. 한국에서 실무 생활을 하며 정말 많은 비전공자 분들이 현업에 종사한다는 것을 알았다. 그리고 그분들이 코딩을 못하는 것도 아니다. 다만, 만약 CS의 기본을 깊게 이해하면 본질을 파악해서 금방 해결할 수 있는 문제도 이리저리 돌아갈 수 밖에 없다. 그게 결국 야근과 철야, 내지는 능력 부족으로 이어질 수 밖에 없는 것이다.

미국에 와서 소위 ‘명문대’ 라는 친구들을 만나보고, 그들과 얘기해 봤을 때 의외로 나보다 아는게 없는 경우도 많은데 왜 이들이 기업에서 소프트웨어 엔지니어로 우대받고, 핵심 개발자로 성장할 수 있는지를 고민해 봤을 때, 결국 그들과 나의 차이점은 얼마나 기본기가 제대로 갖춰져 있느냐는 것이었다. 알고리즘, 자료구조, 컴퓨터구조, DB, OOP, PL 등의 필수 과목에 대한 깊이가 다르니 이미 저 기본 과목을 통해 뿌리를 뻣어나간 이 프로그래밍이라는 세계는 (최소한 내 느낌은) 그들에게는 거기서 거기라는 것이다. 마치 C++을 깊게 이해하면 다른 OOP기반 언어들을 공부하는 데에 크게 문제가 없듯이 말이다.

나의 경우도 그렇다. 나는 중학교와 고등학교 때 경시대회 때문에 알고리즘을 접하긴 했지만, 난 솔직히 반은 억지로 했다. 초등학교 시절인 98년부터 나는 홈페이지 만든 것, 웹 관련된 기술이 좋았고 이런 모듈들을 짜집기 해서 내가 기획한 웹사이트를 만드는 것을 좋아했다. 거기서 오는 사람들의 소통을 즐겼고, 유저 입장에서 fancy한 UI와 기능을 만드는 것을 즐겼다. 자바스크립트와 php, html등을 하던 내게 알고리즘을 굳이 알 필요는 없었지만, 학교에서는 내가 컴퓨터를 잘 다룬다고 알려지자 알고리즘 반에 데려가서는 경시대회를 나가게 했다. GW-Basic과 Q-Basic 등을 배우는 것은 즐거웠고, C언어와 뭐 Turbo-C나 나중에 가서 Visual C++ 6.0이런 IDE가 그저 신기할 뿐이었다. 디버깅을 알고, 학생부 등을 만드는 노가다를 하면서 언어에 대한 사용법을 익혀갔지만 정작 알고리즘을 배운 것은 기본밖에 없었다. 이해하기 쉬운 Floyd, Dijkstra나 배낭문제 정도가 다이지 않았을까. 생각을 요하는 DP보다는, 그저 문제가 주어지면 무조건 brute-force혹은 백트래킹만 돌리고, 퀵소트를 외워다가 혹여나 정렬 문제가 나올까 내심 기대하며 대회(KOI)에 나갔지만 정말 제대로 풀었던 것은 손에 꼽을 정도였다.

사실 그때도 분명 알고리즘을 공부할 기회는 있었지만 나는 방법을 몰랐다. 알고리즘을 잘 하는 애들은 수학을 잘 하는 애들이라고 단정짓고, 나는 이 분야와는 관계가 없다고 스스로 결론내렸다. 2005년에 썼던 글에만 봐도 당시 나의 생각이 고스란이 담겨 있다. 부끄럽지만 당시 고3였던 나의 글을 들춰내본다.

— 2005년 6월 5일

알고리즘, 오랜만에 생각난다. 작년까지만 해도, 정보올림피아드를 준비하면서, 되지도 않는 것 거의 반 강제로 공부하던 것. 그러다 차츰 좋아졌던것.

알고리즘의 종류는 무수히 많다. 알고리즘의 정의는 “문제 해결 능력”이다. 그렇기에 종류가 무수히 많은 것이다. 그러나, 정올에서 쓰이는 알고리즘은 크게 네가지 정도. 그리디, 다이나믹, 백트래킹, 기하알고리즘. 여기서 좀 깊히 들어가면 Divide and conquer , NP 정도가 나올려나..

난 무려 5년이나 알고리즘을 배웠으면서 솔직히 제대로 아는건 별로 없다. 특히, 문제 풀때 그 문제를 보고 바로바로 다이나믹이라고 생각하고, 점화식을 생각하는 애들을 보면 신기하다. 이 알고리즘 때문에, 학원에서 호주로 캠프도 갔었다. 한달동안, 호텔에서 합숙을 하면서 호주 여행도 하면서 공부를 하였다. 한 30여명 정도 됬던가.. 생각해보면 다들 어이없는 애들이다.

초등학생 애들은 거의다가 수학경시대회 전국 손가락 안에 드는 애들이었다. 중학생들은 정올 전국 금상, 은상 정도.. (이 애들은 100% 과고로 빠졌다. 참 어이없다;) 고등학생 형들은 수준이 장난이 아니었다. (이때 캠프에 참가한 형 중 한명은 MIT를 갔다.) 난 그런 소위 영재라 불리는 애들 사이에서 3학년때 구대회 은상이라는 성적밖에 가진게 없었다.

그런 놈들과 한달을 지내면서, 내 실력은 확실히 늘어나진 않았지만 그냥 좋은 경험을 해봤다는 생각만 해 보았다.(한달동안 서울과고 합격자와 같은 방을 썼었다.)

참.. 그렇게 공부했었는데, 고1부터 망해가지고 고2때는 게임 개발한답시고 정올도 소올이 하고.. 결국 고3때 겨우 공부로 돌릴 수 있게 되었다. 참 이 “알고리즘”은 나에겐 별로 친근감이 안느껴지는 존재이다. 하지만, 최근 수학을 많이 접하면서 난 수학과 알고리즘 관의 깊은 상관관계를 느꼈다.

지금 나는 고3 공부를 한다. 알고리즘이라는 5년 동안 나를 잡고 있던 추억이 있긴 하지만, 나는 단지 알고리즘과 비슷한 수학공부를 하고 있다. 하지만, 몇개월 후면 알고리즘은 다른 분야로 다시 나에게 찾아올 것이다. 나는 사실 그것 때문에 공부하는 것일지도 모른다.. 꼭.. 프로그래밍을 하기 위해서..

(지금과는 많이 다른 문체이긴 하지만) 고등학교 3학년 이었던 당시, KOI를 약 5년 정도 준비하다 고2때 수능 공부를 위해 모든 것을 접었었다. 거의 중 고등학교때의 인생이 KOI라고 봐도 과언이 아니었는데, 이때부터도 나는 KOI를 대입의 등용문이라는 그릇된 생각과 함께 문제해결에 집중한 것이 아니라 배운 것을 가져다 쓰는 것에만 집중했다. 결국 수능을 통해 대학에 가게 되었지만, 알고리즘 = KOI 라는 생각에 이를 5년간 준비해 ‘실패’ 했다는 생각에 선듯 알고리즘을 잡지 못했던 것 같다.

그런데 대학이나 과학고, 입시 그런게 무엇이 중요하던가. 정말 12년이 지난 지금에서야 느끼지만 알고리즘은 어떠한 성공의 수단이 되는 것은 절대 아니라는 것. 그걸 성공과 결부시킨 나 스스로도 도통 이해되지 않지만, 대입, 고입 등에 눈멀어 본질적인 즐거움을 느끼지 못한 것이 더 크지 않았을까. 아마 알고리즘 잘해서 대학간다 는 이상한 믿음이 없었다면 되려 더 혼자 관심가지고 공부했을지도 모르겠다. 이후 12년을 살다 보니 하물며 대학, 대학원 시절 공부를 오로지 학점에만 목메어 행하던 나의 모습이 부끄럽기만 하다.

결국, 그 어떤 것에도 멋이란 존재하지 않는다. 다만 나의 즐거움만 존재할 뿐이다. 지금 내가 비록 취직을 위해 알고리즘을 공부한다 하지만 언젠가는 보고 싶었던 것이고 취업과는 별개로 스스로 흥미를 느끼고 즐거워 하고 있다. 수학이 어렵다, 증명이 어렵다, 시간없다, 영어 등등 이런건 이제 대학원까지 마친 내게는 핑계밖에 되지 않는다. 2018년에 어떤 취업을 통해 직장생활로의 복귀를 바라고 있지만 결국 내가 내년에 극복해야 할 부분이 그것이다. 프로그래밍을 접한 지난 20년동안, 기본기를 철저히 하고 프로그래밍의 철학을 더 깊게 다지는 연습을 꾸준히 하는 것. 물론 작품을 만드는 것은 계속되겠지만, 진정한 소프트웨어 엔지니어란 무엇인지에 대해, 소프트웨어에 대해, 더 나아가 소프트웨어와 내가 꿈꾸는 웹에서의 그 세계가 갖춰갈 미래에 대해 지속적인 공부를 하는 것이 2018년의 가장 큰 목표가 아닐까.

말은 이렇게 길게 했다만, 결론은 알고리즘 공부는 끝이 없을테고, 2018년 전까지는 기본기를 확실히 다지고, 더 다지기 위해 문제를 꾸준히 풀어나가고, 문제를 풀어나가는 것이 결국 문제해결 능력과 다양한 스스로가 배워온 것들의 종합이다. 그것이 소프트웨어 개발의 본질일 것이고, 지금의 내가 확고히 다져야 할 큰 부분중 하나이다. 결론은, 2018년에는 엉덩이가 무거운 사람이 되자.