좋은 코드

예전에 어떤 버그하나를 추적하고 있었다. 문제를 이해하려고 관련된 코드를 쭉 읽어내려가다보니 어느순간 짜증이 솟구쳐 올랐다. <이거는 어떤 자식이 코드를 짰길래 이딴식이야!> 하며 git 히스토리를 열어보니… 그건 몇년전 나였다. 아마도 릴리즈가 급한 나머지 코드의 퀄리티에 신경 안쓰고 일단 돌아가는것에 집중했던 시기였던것 같다. 같은 코드를 오랫동안 만지는 여러 개발자들이 비슷한 경험을 하지 않았을까?

대부분의 사람들은 동작하는 코드를 만들수 있다. 어떤 사람들은 <빠르게> 동작하는 코드를 만들수 있다. 그보다 적은 수의 사람들은 <이해할수 있는> 코드를 만든다. 소프트웨어 회사의 매출은 동작하는 프로그램에서 나오지만, 회사의 진짜 자산은 (커피만 마시고) 코드를 만들어낼수 있는 프로그래머와 그 사람들이 수년간 만들어낸 지식의 총체인 방대한 코드베이스다. 예를들어 2015년 기준 구글의 코드베이스는 20억 라인이라고 한다. 단기간의 성공을 위해 우선 동작하는 프로그램을 만들수는 있지만 SW조직의 수명은 코드의 퀄리티에서 결정된다. 코드를 만들때는 각자 자기의 성을 짓는것과 같다. 그런데 몇년후 자신이 만든 성에 들어가서도 우리는 길을 잃는다. 현실에서 회사는 남이 만든 초가집을 성이라 우기며 아름다운 탑을 몇개 더 붙이라고 요구한다.

“Programs must be written for people to read, and only incidentally for machines to execute.”
“코드는 남들에게 읽히는게 목적이지만, 종종 컴퓨터가 실행하기도 한다”

예전엔 코드가 화려할수록, 복잡해 보일수록 뛰어난 것이라 생각했다. 그런데 이전 블로그에서 설명한대로 프로그래머의 자존심으로 채워진 화려한 코드는 스타트업 하나쯤은 쉽게 무너뜨릴수 있다. 수년간 더 여러 팀에서 일하고 난 지금은 좋은 코드를 이렇게 정의한다.

<당연하게 읽히는 코드>

이전 회사에서 테크 리드로 있으면서 많은 코드를 리뷰했다. 팀원은 이제 갓 대학을 졸업한 어린이(?)부터 20년 경력의 백전노장까지 다양하게 구성되어 있었는데, 그 중 J는 특히 코드 퀄리티에 관심이 많았다. 경험도 많고 듣기로는 인터뷰를 퍼펙트로 통과했을정도로 스마트한 친구였다. 이 친구가 짠 코드를 읽으면 <와우> 이런 감탄사는 나오지 않는다. 단지 코드의 처음부터 끝까지 논리의 흐름이 너무나 당연하게 읽힌다. 마치 J가 만든 성안에 처음 들어가 구석구석 살펴 보는동안 그가 옆에서 친절하게 길을 안내해주는 느낌이다. 그런데 <당연하게 보이는 코드>를 만드는게 사실은 가장 어려운 것이다. J는 스스로 길을 안내하는 코드를 만들기 위해 속도를 희생했다. 그는 어떤때는 좀 답답하게 느껴질정도로 코드를 천천히 만들었다. 어떤때는 괜찮아 보이는 코드들도 처음부터 다시 하겠다고했다. 그렇게 나온 코드는 너무나 당연히 읽히기에 쉽게 이해할수 있었고 고칠 부분이 거의 없었다. 당연히 버그도 나오지 않았다.

이와 반대로 이제 막 학교를 졸업한 어린이(?) 엔지니어들의 코드는 읽으면서 감탄사가 나온다. 여과해 <아 이딴식으로도 생각을 하는구나> 이 정도로 표현해야겠다. 그 코드는 분명히 목적대로 정확하게 동작한다. 유닛 테스트도 충실하게 채워서 논리의 부분 부분을 모두 커버한다. 그런데 아무리 읽어도 당연하지가 않다. 이상하다. 코드가 자신의 논리 흐름을 스스로 설명하지 못한다. 비유하자면 조그만 초가집에 리뷰하러 들어갔는데 그게 미로같은 동굴의 초입이었던거다. 거기에 더해 주니어는 승진 욕심에 코드를 시니어보다 더 빠른 속도로 만들어낸다. 몇년전 여름에 잠깐 일했던 인턴은 열성이 넘쳤다. 아마도 짧은 인턴쉽 기간동안 어떻게든 강한 인상을 남기고 싶었을것이다. 그래서 그 인턴은 석달 내내 코드를 만들어대며 리뷰를 요청했다. 계속 만들어내는 그 이상한 코드를 몇시간씩 리뷰하다가 이런 생각이 들었다.

147255590836907.jpg
(물론 이렇게 얘기하지 않았다)

그런데 <당연하게 읽히는> 에서 당연하다는 것이 몹시 주관적이다. 내게 당연한것이 다른 사람에겐 이상할수 있다. 하지만 경험상 어느정도 퀄리티를 갖춘 시니어로 구성된 팀이라면 한 시니어에게 당연해 보이는 코드는 다른 대부분 시니어에게도 자연스럽다. 주니어의 눈으로 보기에 자기들끼리 밀어주고 당겨주고 하는것처럼 보일수도있다. 하지만 그런것이 아니다. 코드의 퀄리티를 높이는 요소는 객관적으로 정의내리기 어렵지만, 경험자 사이에서 수렴되는 <보면> 알수있는 퀄리티의 요소가 있다. 평점 9점의 영화가 왜 훌륭한지 이유는 관객마다 조금씩 다를수 있다. 그런데 모든 사람들이 <아 좋았어> 라고 공감하는 퀄리티가 있는것이다.

가장 중요한 퀄리티는 <추상화> (Abstraction) 이다. 추상화의 가장 큰 오해중 하나는 <추상화 그림>처럼 현실을 모호하게 표현하는 것이라 생각하는것이다. 추상화의 본질은 감출것은 감추고, 드러낼것은 드러내는 것이다. 좋은 코드는 읽는 사람에게 가장 적절한 추상화의 단계 (level of abstraction)를 선사한다. Class, Function, Variable의 이름과 관계를 통해서 리뷰어가 읽으며 예측하고있는 단계의 추상화를 바로 그 순간 보여주는것이다. 성으로 들어가는 리뷰어가 문같은 형태를 찾고있는데 문의 열쇠를 보여주는 것은 리뷰어를 혼란스럽게 만들뿐이다. 좋은 추상화는 리뷰어가 문 앞에 다가간 그 순간에 문의 열쇠를 보여주는것이다. 성의 문을 하나 하나 열때마다 그 레벨에서 예측가능하고 익숙한 컨셉으로 논리의 방을 설명하는것이다. 추상화의 각 레벨에서 모두에게 <익숙한 컨셉>으로 설명하기 위해서는 많은 코드를 읽는것이 필요하다. 비슷한 유형의 문제에 대해 사람들이 공통적으로 동의하는 코드의 패턴이있기 때문이다. 나는 코미디언 <코난 오브라이언>을 좋아하는데 그의 팟캐스트를 듣다보면 항상 킥킥대던 그가 종종 진지한 주제로 대화할때가 있다. 그건 다른 코미디언이 호스트로 나오는 에피소드들이다. 코난과 다른 코미디언은 서로 뛰어난 코미디의 요소에 대해 진지하게 질문하고 탐색한다. 시대를 앞서간 코미디언들의 <익숙한> 패턴을 알고 싶어서 얼마나 연구했는지 서로 나누는 그 에피소드를 들으며 <직업>이 무엇인지 새삼 생각하게된다. 프로그래머가 새로운 것을 모두에게 익숙하게 설명하는 그 <당연함>의 이면에는 많은 시간 읽어내려간 방대한 코드의 양이 있다.

단계적 추상화를 마스터한 경험자와 초보의 가장 큰 차이는 논리의 흐름을 What 과 How로 설명하는 차이다. 좋은 코드는 추상화의 단계가 깊어질때마다 <이것은 무엇(What)입니다> 를 반복하고 주니어의 코드는 <이것은 어떻게(How) 돌아갑니다>를 반복한다. 주니어의 코드를 리뷰할때면 <이것은 귀가 쫑긋합니다> <이것은 짖습니다> <이것은 귀엽습니다> 와 같은식으로 여러개의 <How>를 붙여 무언가를 설명한다. 그럼 나는 <이거 개야?> 묻고 주니어는 그제서야 <아 개네!> 깨닫는다. 처음부터 대상이 개라고 설명했다면 나는 개의 동작과 특성에 익숙하므로 노력없이 논리를 이해했을것이다 (최악의 경우는 저렇게 설명해놓고 고양이라고 우기는 상황이다). 표현하고자 하는 논리를 모두에게 익숙한 컨셉 (What)들 사이의 관계로 설명하는것은 OOP에 좀 더 가깝다. 또한 논리를 <선언 (Declaration)>의 연속으로 표현하는 함수형 프로그램도 이에 가깝다. 그러나 <What>과 <How>중 무엇을 강조하는지는 OOP, 함수형 언어보다 코드를 만드는 사람의 경험과 내제된 퀄리티에 더 관계가 있다.

“Bad programmers worry about the code. Good programmers worry about data structures and their relationships.” – Linux Tovalds
“안좋은 프로그래머는 코드에 대해 걱정한다. 좋은 프로그래머는 데이터 구조와 관계에 대해 걱정한다” – 리누스 토발즈

끝으로 어느 팀이든 좋은 코드를 마스터한 시니어만으로 구성되지 않는다. 프로그래밍팀은 하나의 마을이다. 거기엔 아름답고 웅장하게 세워진 성도 있고 이제 첫 삽을 떠본 주니어가 만든 초가집도 있다. 시니어의 역할은 주니어의 초가집 엉성한 부분을 지적하는것에서 끝나지 않는다. 진짜 마스터는 계속해서 자기 성을 짓는 사람이다. 주니어가 지켜보며 영감 (inspiration)을 얻을만큼 계속해서 조금 더 아름다운 성을 만드는 사람이다. 주니어의 초라한 집에서 훗날 성이 될수 있는 재능을 발견해 용기를 주는 사람이다.

https://twitter.com/sm_park

코더

예전에 한 대기업 주재원분과 짧게 이야기 나눈적이 있었다. 내가 박사후에 계속 개발일 하고 있다고 했더니 <예? 코더요?> 하며 약간 그분 눈이 커진것을 놓치지 않았다. 도대체 코더가 어떻길래, 저 반응은 어떤 뉘앙스일까 살짝 마음에 걸렸다. 1년마다 다시 돌아오는 <잡스는 커녕!> 뉴스기사를 보고 그게 어떤 의미인지 조금 더 명확하게 다가왔다. (뉴스 기사)

기사의 도입부는 이렇다. “지난 6일 서울 관악구 서울대 공과대학에서 만난 하순회 컴퓨터공학부 학과장은 제 4차 산업혁명 시대에 고급 개발자 양성이 가장 중요한데도 현재는 부족한 개발자 인력을 채우기 급급해 ‘프로그래머’만 양성하고 있다고 진단했다. 여기서 하 학과장이 언급한 프로그래머란 단순 코더(Coder)에 가깝다. 고급 개발자가 프로그램 전반을 기획하는 설계자라면, 코더는 이를 실현하는 시공자에 해당한다.”

일단은 기사의 의도 자체가 <학교에 돈 좀 줘…제발> 인것은 기사에 쓰인 <공과대학 전경>이미지를 보면 알수있다 (골라도 저런 사진을…) 그렇다해도 코딩하는것을 천직으로 여기고 사는 나같은 사람은 이 기준으로 그럼 고급이냐 단순이냐 의문이 들수밖에 없다. 나뿐 아니라, 존경해 마지않는 <제프딘> <제임스고슬링> <크리스라트너>… 이 사람들은 분명히 고급일텐데 아직도 코딩을 하니, 이 비유대로라면 세계적인 건축 디자이너가 현장에서 공구리치고 있다는 얘기잖아?

문제는 소프트웨어를 <설계>한다고하니 자꾸 건축업계에서 메타포를 가져와 설명하려는데있다. 설계와 시공이 분리되어있고 고급진(?) 사무직과 현장직이 분리된 산업을 비유해 설명하니 자꾸 이 직업이 오해를 받는다. 내가 아는 뛰어난 개발자들은 모두 실제로 코딩한다. 처음 커리어를 시작할때도 그렇고 나이와 명성이 쌓인후에도 마찬가지다. 제프딘과 Sanjay의 협업에 대해 소개한 New Yorker 최근 기사는 구글의 탑레벨 임원인 그들이 매일 코딩한다는것을 잘 보여준다. 최근에 나는 회사를 옮기며 인터뷰를 했는데, 경력 10년에 어느정도 규모의 팀을 매니지했던 이전 역할과 상관없이 가혹한 코딩테스트를 거쳤다. 10년, 20년차의 경력만 내세우고 코딩을 소홀히 한 사람들은 <쏘리 쏘리> 연발하다 인터뷰를 마치기 십상이다.

그럼 프로그래머를 설명할 적당한 다른 직업은 없을까? 나는 개발자는 연예인에 좀 더 가깝다고 생각한다. 가수는 무대에서 노래를 불러야 가장 빛나듯이 개발자는 컴퓨터앞에서 코드와 싸울때가 가장 어울린다. 나이가 들어 무대뒤에 숨어서 후배들만 가르치려드는 가수보다는 계속 무대에 나와 조금 더 잘 하려고 애쓰는 사람을 아티스트라는 말로 표현한다. 아침마당에 나와 유연하게 허리 돌리는 사장님 박진영과 비의 퍼포먼스는 나이든 개발자가 지향해야 할 모델이다. 폴그레이엄은 에세이에서 개발자를 화가에 비유하기도 했다. 미술관의 주인공은 큐레이터가 아니고 아티스트인것을 잊지않았음한다.

기사에서는 고급개발자를 <양성>할수 있다고 주장했다. 개발자들 사이에서는 능력의 차이가 실제 크게 존재한다. 한때 10x 엔지니어라는 말이 유행했는데, 일반과 고급의 성능차이를 10배로 추정한다는 뜻이다. 나는 내 경험을 토대로 고급개발자의 조건을 세가지로 요약하려한다.

  1. 코딩이 뛰어나다면

코딩을 잘하는 사람은 많지 않다. 대충 경험상 네명중 한명정도 잘한다. 코딩은 엔지니어링 프로세스의 가장 중요한 한 부분이고, 좀더 넓게 표현하면 문제해결능력이 고급개발자의 조건에 가깝다. for-loop, if/else 등의 로직 연산으로 구성된 코딩은 사실 사람이 매일 수행하는 연산이다. 그래서 쉽게 보여 뛰어들수 있지만 일단 시작하면 죽을때가지 마스터할수 없는 수행의 길이다. 이 고난의 길에서 탁월한 기량을 보이는 사람은 두가지 정도로 나뉠수 있다. 첫째는 타고난 지능이다. 지금까지 학교졸업하고 막 직업전선에서 코딩을 시작한 여러명의 주니어들이 성장하는것을 지켜봤다. 그 과정에서 부인할수 없는것은 어떤 사람들은 불공평하게 똑똑하다는것이다. 브레인 자체의 배기량이 커서 한번에 처리하는 복잡도의 양이 다르다. 세상은 불공평하고 나 역시 불공평한 세상에 선택받지 못한자로 태어났다. 하지만 아직 찬스가 남아있는것은 두번째 이유 때문이다.

두번째 자질은 문제해결을 즐기는 사람이다. 많은 사람들에게 이 문제들은 괴로운 것이고 월급이라도 받아야 간신히 참여하는 노동인데 어떤 사람들은 그 과정 자체를 즐거워한다. 사실 똑똑한 것과 즐기는 것은 그 둘사이에 크게 연관성이 없다. 배기량이 조금 부족한 차를 몰아도 운전하는게 즐거워 매일 드리프트하다보면 배기량 큰차와 레이싱 붙어도 꿇리지 않는다. 내가 조립해놓은 생각의 조각들이 서로 맞물려 한치의 오차없이 돌아가는것을 지켜보는것은 세상에서 가장 즐거운 일중 하나이다. 나는 이번에 회사를 이직했는데, 지난주 회사를 나오며 약 반년간 작업한 결과물을 런치했다. 스케줄이 밀려 마지막날 금요일에 버튼을 눌러야했는데, 동료들에게 이걸로 나는 회사의 <레전드> 아니면 <빌런>으로 남을거라며 웃었다. 높은 확률로 서버가 터질수 있고 그 경우 회사의 매출에 직격탄을 맞는 백엔드 작업이다. 다행히 난 <레전드>로 마무리할수 있었다. 그 이유는 마지막날 새벽 3시까지 근심어린 눈으로 서버 그래프를 지켜볼 정도로 나는 이 문제를 내것으로 여기고 좋아했기 때문일것이다.

  1. 태도역시 겸손하다면

꽤 오래전 스타트업 직장에 정말 뛰어난 개발자 친구 C가 있었다. 수십만 라인의 코드를 몇달만에 만들어내는 어려서부터 코딩한 타고난 해커다. 제품 첫 버전의 거의 70%정도를 C 혼자 작성했다. 내가 처음 들어가 그 친구 코드의 이해안가는 부분을 질문했을때 흔쾌히 설명해준 다음 자신의 구현이 경쟁자에 비해 얼마나 빠른지 그래프까지 보여줬다. 경쟁 오픈소스 제품에 대해 설명할때면 다소 경멸띤 표정으로 얼마나 자신의 구현이 우월한지 설명하곤했다. 그런데 경쟁 제품이 시장에서 인기를 더 얻기 시작했다. 회사는 버전 2를 만들어야했고 가장 중요한 부분은 역시 C군에게 맡겨졌다. 다른 개발자들에겐 그 문제가 너무 어려울거라 생각했는지 C군은 문제를 독점했다. 그게 문제의 시작이었다. 버전 1에 비해 훨씬더 복잡한 스펙을 요구했던 버전 2는 C군에게도 버거운 문제였다. 하지만 그는 도움을 청하지 않았고 버전 2는 계속 지연됐다. 나중에는 문제가 지겨워졌는지 아프단 핑계로 한동안 회사에 나오지도 않아 그당시 우리 VP는 치킨누들수프를 끓여서 그 친구집으로 배달을 가곤했다. 스케줄보다 1년넘게 지연된 버전 2는 나온 후에도 버그 투성이였다.

코딩이 뛰어난데 겸손한 개발자 찾기는 정말 쉽지 않다. 어느정도 규모있는 팀에서 일하는 사람은 무슨 의미인지 알것이다. 경험상 두명중 한명꼴로 본받을만한 겸손함을 갖고있었다. 뛰어난 개발자는 높은 비율로 똑똑하기 마련이고 어려서부터 똑똑했던 사람에겐 겸손이 어려운 문제다. 하지만 똑똑한데 오만한 개발자는 팀에 있어서 독과 같다. 디자인, 코드 리뷰를 할때면 어느 순간 브레인의 배기량 자랑으로 변해버려 상대를 짓눌러버릴 방법을 찾는다. 오만한 시니어가 주도하는 팀은 각자도생하는 정글로 변해버린다. 정말 뛰어난 개발자는 혼자서 버전 1은 만들어낼수 있다. 하지만 궤도에 올라간 프로덕트를 우주로 끌어올리는건 팀이 함께 푸쉬하는 힘이다. 그리고 그팀을 만들어내는건 코어에 있는 능력을 겸손한 말로 전달하는 리드다. 겸손함의 핵심은 상대방과 팀을 돕기위해 자신을 내어주는 것이다.

  1. 그런데 커뮤니케이션도 잘하면

훌륭한 코딩에 겸손함을 갖추고 있는 개발자가 주위에 있는지 생각해보라. 혹시 그 사람이 팀에 미치는 영향력이 생각보다 작다면 마지막 조건에 미달하기 때문일것이다. 커뮤니케이션과 코딩능력은 정말로 어울리지 않는 상극과 같은 조건이다. 왜 그런지는 나도 잘 모르겠다. 주변에 코딩 정말 잘하는데, 자신의 문제를 비지니스에 연결지어 효과적으로 설명하는 사람이 얼마나 되는지 생각해보라. 경험상 세명에 한명 꼴로 개발자의 커뮤니케이션이 좋았다. 야후의 Marisa Mayer는 이렇게 얘기했다.

“Beyond basic mathematical aptitude, the difference between good programmers and great programmers is verbal ability.” – Marissa Mayer

“기본적인 수학능력 이외에 괜찮은 프로그래머와 뛰어난 프로그래머의 차이는 말하는 능력이다”

나는 지난 몇년간 매니저 역할을 하면서 수도없이 많은 미팅을 했다. 사실 매니저 시작하며 제일 부담스러웠던건 내 떨어지는 영어실력과 발음이었다. 하지만 몇달 지나고나서 내 걱정은 기우였다는 것을 알았는데, 영어가 모국어인 사람들도 말을 엄청못한다는걸 깨달았기 때문이다. 1:1 미팅하면서 지금 해결하는 문제에 대해 질문하면 눈을 잘 못 마주치며 우물대는 사람도 있고, 전달해야 할 내용을 요약을 못해 코드 레벨 하나하나 다 설명해야 하는 사람도 있다. 커뮤니케이션을 잘하는 것은 말을 많이하는것이 아니다. 어떤 친구들은 말하는 것을 너무 좋아해 정보에 시그널 대비 노이즈가 너무 많다. 커뮤니케이션이 좋은 사람은 상대방에게 필요한 정보를 정황 (context)속에서 빨리 캐치해내고 상대의 언어로 해석해서 전달한다. 개발자와 PM/마케팅같은 비 개발자가 모이는 미팅에서 개발자가 사용하는 단어 하나하나를 유심히 살펴보라. 외계언어로 이야기하는 개발자에게 미소를 짓는 마케팅 부서 직원은 <이 외계인이 또…> 속으로 생각할런지 모른다.

코딩 잘하는 사람이 1/4, 겸손한 사람이 1/2, 마지막으로 커뮤니케이션 잘하는 사람이 1/3 비율로 존재한다면, 이 세가지를 모두 갖춘 사람은 1/24 비율이다. 이렇게 찾기 어려우니 고급 개발자인게 맞다. 그런데 이 세가지 조건중에 학교에서 양육할수 있는것은 무엇인지 생각해보라. 겸손을 학교에서 배울수 있을까? 다양한 직종의 사람들 틈사이에서 배워가는 커뮤니케이션 능력은 어떨까? 코딩의 영역 역시 학교는 정글에서 살아남는 도구 쓰는 능력을 가르칠뿐 실력 자체를 만들어주지는 못한다. MIT, 스탠포드, 아이비리그 학교의 졸업생들 많이도 일해봤지만, 흔히 이야기하는 학교의 네임밸류와 실제 코딩 능력은 크게 연관성이 없었다. 뛰어난 리더는 양육되는게 아니다. 혹시 가능하더라도 최소한 양육하는 스승이 뛰어난 모델이어야 하지않을까? 누군가가 <교수는 졸업하지 않기로 마음먹은 학생>이라고 이야기했는데…

코딩, 겸손, 커뮤니케이션을 마스터한 뛰어난 리더는 살면서 그렇게 하기로 스스로 깨달은 사람들이다.

https://twitter.com/sm_park