이 글은 개발자들이 성장하면서 겪는 어려움을 적은 글이다. 참 길다. 그리고 좀 뒤에는 전문적인 용어도 조금 나온다. 급한 분들은 다 skip하고 저 아래 그림을 일단 보시고, 그림 다음에 있는 각 단계별 설명에서 각 문단의 첫번째 문장 정도를 훑고 넘어가면서 공감 또는 이해를 해주시면 감사하겠다.

---

서론: 소프트웨어는 이제 매우 중요해졌다. '이제'라고 하기엔 그 중요성이 너무 늦게 발견되었지만 말이다. 누구나 소프트웨어를 배우는 것이 좋겠다고 한다. 그 이유는 예전에 썼던 글에서 이야기했다.

     왜 모두가 소프트웨어를 배워야 하는가? <-- CLICK

모두가 소프트웨어를 배워야 한다는 것은 모두가 개발자가 되어야 한다는 뜻은 전혀 아니다. 가벼운 코딩을 통해 소프트웨어를 경험하는 것은 모든 사람이 발레나 심각한 요가 자세가 아닌 스트레칭을 배우는 것과 비슷하다. 스트레칭을 통해 있는지도 몰랐던 근육들이 내 몸 안에서 움직이고 있다는 것을 느끼는 것처럼 누구나 소프트웨어를 배우고, 가능하면 코딩도 해봐야, 그토록 중요하다는 소프트웨어가 뭔지 몸으로 느껴보고, 소프트웨어 개발자들과의 소통 능력을 키우기 위함이다.

그렇다면 소프트웨어 개발자가 되는 것은 어떻게 다른가? 개발자란 소프트웨어가 결국 현실화하려는 가치를 코딩이라는 도구로 구현하는 사람을 말하며, 대개는 그것을 직업으로 삼는 경우를 특히 의미한다. 그런데, 좋은 훌륭한 개발자가 되기는 쉽지 않다.

프로그래머와 개발자는 어떻게 다른가? 라는 질문도 흔히 한다. 내 답은, 프로그래머는 프로그램을 어떤 이유에서든 짜는 사람을 말하고, 개발자는 고객이 있는, 즉 의식적으로 사용자를 고려하면서 프로그램을 짜는 사람을 말한다. 학교에서 주어진 프로그래밍 과제를 하면서, 또는 책에 있는 연습 문제를 풀면서 프로그램을 짜는 학생들을 개발자라고 부르기 어렵다. (이 해석에 대해 논란이 있을 수 있다.)

이 글에서는 흔히 개발자가 밟는 발전 단계를 이야기하고자 한다. 이 단계는 책에 나온 것도 아니고, 모든 사람이 이렇게 되는 것도 아니지만, 내 경험에 의하면 많은 개발자들이 겪었을 단계라고 생각된다. 아마 이 글을 읽는 사람 가운데 '천재 개발자' 있을 것이다. 그들은 다른 종족이다. 이런 설명이 잘 안통한다. 다행히도 그런 사람이 별로 없다. 또 소프트웨어가 적용되는 산업 도메인 별로 생산성 향상을 위한 훌륭한 도구들이 많이 존재하기 때문에 어떤 영역에서는 아래 설명하는 단계를 거치면서 배움이 일어나지 않는 경우도 있을 것이다.

하지만, 보통은 이런 식이다. 이 설명으로 소프트웨어 배우고 있는 '내가' 지금 왜 어려움을 겪고 있는지 이해하고 대처하면 좋겠다. 소프트웨어(컴퓨터 공학/과학)을 전공하는 학생이던 전공과 상관없이 소프트웨어를 배우는 사람이던.

여기서는 소프트웨어를 배울 때 겪는 어려움을 5단계로 나눈다. 우리가 구구단을 열나게 외우고/헷갈리다가 어느 날 구구단이 더 이상 문제가 되지 않는 시기가 있듯이 소프트웨어를 배울 때 누구나 경험하는 것은 점진적이 아닌 계단형 발전이다. 그게 아래 그림이다.

또 각 단계에는 약간의 부침이 있다. 그 부침을 겪다보면 어느 순간 다음 단계로 넘어간 자신을 발견하게 된다. 사람마다 또 그 사람이 가진 열정에 따라, 투입한 시간에 따라 각 단계별 극복 기간은 다소 달라지겠다.

 

1 단계 : 코딩을 배우는 1 단계의 첫 번째 어려움은 소위 말하는 Computational Thinking 그 자체다. 아주 간단한 문제도 논리적 절차적으로 펼쳐내기가 어려운 단계이다. 대부분의 컴퓨터 언어는 쓰여진 순서로 한 문장, 한 문장씩 순차적인 실행을 하게 되는데, 인간의 생각은 그렇게 세세한 절차를 생각하면 행동하지 않는다. 그저 '학교에 가요', '밥을 먹어요' 라는 엄청나게 큰 규모의 행위가 생각날 뿐, '수저를 들고, 밥을 뜨고, 입에 넣고, 수저 놓고, 젓가락 들고, 반찬 고르고, 콩나물 집고, 입에 넣고, 젓가락 놓고, ...' 이렇게 생각을 펼치지 않는다. 또 펼쳐진 개별 행위조차 잘 생각해보면 엄청난 세부 절차들로 구성된 일들이다. 그래서 처음 프로그램을 짜면 어느 정도까지 세부적으로 펼쳐야할지에 대한 고민도 많고, 놓치는 것이 많다. 

1 단계의 두 번째 어려움은 프로그래밍 언어 그 자체에 있다. 스크래치나 엔트리와 같은 교육용 언어가 있지만, 역시 앞서 이야기한 펼침의 어려움은 그대로 존재한다. 더우기 가장 쉽다는 파이썬, 하물며 자바, C, 자바스크립트 등은 처음 프로그램 하는 사람들에게는 암호에 가까운 물건이다. 자연언어와는 하등의 상관이 없어보이는 유드리 없는 문법과 키워드들은 꽤나 높고 두꺼운 벽이다. 또, 조건문, 순환문, 함수와 같은 개념도 절대 쉽지 않다. 게다가 변수 (뭔가를 저장해야 한다는) 개념은 우리가 일상에서 생각해보지도 못한 것이다.

1 단계의 어려움은 소프트웨어를 배우려는 자발적 동기가 없거나 부족한 학생들에게는 너무 큰 문제이다. 초중등, 비이공계 소프트웨어 (코딩) 교육이 극복해야할 가장 중대한 이슈인 것이다. 1 단계의 어려움은 쉬운 문제들을 많이 풀어보는 것으로 극복이 된다. 놀라운 것은 한 가지 프로그래밍 언어를 배우고 나면, 요즘 유행하는 함수형 언어처럼 개념 자체가 다른 경우를 제외하고는 다른 언어도 기본이 같구나, 그냥 조금 시간 내서 배우면 되겠구나 하는 생각이 들면서 2 단계로 넘어간다. 온갖 설명이 안 통하는 더 어린 친구들(즉, 차례대로, 순차적으로 뭐 이런 단어가 설명이 안되는 친구들)에게는 이 1 단계에 특단의 조치가 필요하다. 즉, 그 친구들이 이전에 알고 있던 '차례로'의 개념에 문제를 Visual하게 매핑하는 '신공'이 필요하다고 본다.

2 단계 : 코딩을 배우는 2 단계의 첫번째 어려움은 데이터에 대한 이해이다. 우리는 '학교에 가요' 처럼 어떤 행위를 퉁쳐서 말하듯이 데이터 또한 퉁쳐서 말한다. '학생', '책' 뭐 이런 식이다. 학생이 학생이기 위해서는 '이름', '학번', '기타 개인정보', '학기 별 성적' 등 수 많은 데이터가 같이 움직여야 한다. 사람은 당연히 그런 것이 가정되었다고 믿지만, 프로그램을 만드는 사람은 그 각각을, 또 그 각각 데이터의 다시 세부적인 내용들을 모두 독립적으로 드러나게 선언하고, 처리해야 한다. 말은 쉽지만 이런 생각을 하기란 전혀 쉽지 않다. 이 어려움은 1 단계의 어려움과 맥을 같이 한다. 사람은 행위와 데이터를 구분하지 않고 한 방에 일을 처리한다. 사람은 너무 위대하고 컴퓨터는 그저 저장된 명령을 차례로 실행하면서 저장된 데이터를 처리하는 기계일 뿐인지라, 사람이 기계의 패러다임에 맞추기는 쉽지 않다. 뭔가를 쪼개고 구분한다는 것을 설명하기 어려운 어린 친구들에게 이 어려움은 아마 더 심각할 것이다. Visual하게 매핑한 1 단계에 이 데이터라는 것을 '잘' 숨겨야 할 것이다. 어린 것들에 대한 Computational Thinking 교육에 '분류'가 자주 등장한다. 즉, 다리가 네개인 동물, 두개인 동물 등 보이는 것의 일부를 보고 그것을 기준으로 뭔가를 하게 하는 이유가 그것이다.

2 단계의 두 번째 어려움은 각 프로그램 언어들이 명시적으로 또는 묵시적으로 처리하는 데이터 타입의 다양성과 그 데이터를 처리를 위한 구조적 표현 방식을 개념적으로 이해하는 일이다. 벌써 어렵다. 여기에는 (C언어의) 포인터, 다양한 자료구조, 객체 지향언어의 객체라는 개념 등이 포함된다. 각 데이터/객체 형식이 가질 수 있는 특징과 동작들은 사람이 생각하는 방식을 따라 만들었다고는 전혀 믿기지 않을 정도로 어렵다. 또 자료구조와 같은 과목에서 우리는 2 단계를 배울 때 비교적 쉬운 알고리즘을 같이 배우기도 하지만 편의상 그렇게 배울 뿐 2 단계의 여려움은 알고리즘이 아닌 데이터 표현/처리 방식이 사람이 해왔고 느끼는 방식과 다름에서 오는 어려움을 의미한다. 특히 객체지향 언어에서의 객체는 위 2 단계의 첫 번째 어려움에서 언급한 사람의 행동 방식 (데이터를 구분하지 않는다는)과 개념적으로는 상통하지만, 프로그래밍 언어가 그것을 억지로 분리해서 생각하라고 우기는 형상이다.

통상적으로 비전공자 즉 소프트웨어 개발자 트랙이 아닌 사람들에게는 2 단계의 첫 번째 어려움을 극복하는 수준까지의 교육이 필요하다고 본다. 자신이 가진 문제가 어떤 식으로든 간단하지 않은 데이터들과 관련이 있고, 그 문제를 프로그래밍 언어가 규정하는 문법에 따라 논리적 절차적인 방식으로 해결되어야 함을 느끼고, 경험하는 것을 배우면, 개발자와의 최소한 소통 능력을 가질 수 있다고 생각한다.

3 단계 : 3 단계는 프레임워크의 이해이다. 3 단계의 첫 번째 어려움은 이전에 자동으로 된다고 믿었던 것들이 원래부터 존재하는 것이 아니었다는 것을 깨닫고, 그런 것이 없는 영역의 경우, 개발자 자신이 그것을 만들어야 했었다는 점을 수용하는 것이다. 여기에서 프레임워크라 함은 요즘 말하는 그 프레임워크일 수도 있고, 운영체제, 표준 라이브러리 등 우리가 직접 작성하지 않고 이용하는 모든 것과 컴파일러, IDE, Issue 관리, 리뷰, CI를 포함하는 프로젝트 도구까지를 의미한다. 이 3 단계를 극복하는 수준에 이르면, 프레임워크의 아름다움 때문에, 새로운 프레임워크와 맞는 프로그래밍 언어, 도구들을 배워야 할 자발적인 학습 동기가 생기기 시작한다. 

3 단계의 두 번째 어려움은, 잘 만들어진 프레임워크들을 사용할 때, 그 동작이 생각보다 정교해서 적어도 한 번은 내부의 디테일을 따져봐야 한다는 점이다. 실제 프로젝트에서 그 프레임워크를 이용해 보는 과정에서, 각  API, 함수, 기능들의 동작, 리턴값, 자료의 전달, 에러메시지 등 매뉴얼에 나와있는 내용들을 속속들이 이해해야 한다. 그리고 누가 만들어도 그렇게 만들었어야 했구나 라는 점을 깨닫는 과정을 경험하는 것이다. 이 과정이 프로 개발자가 될 때 가장 중요하며, 이 과정을 어설프게 넘어가면 품질이 낮은 프로그램을 생산하게 된다. 3 단계를 거치면서는 코드 리뷰와 같은 개발 프랙티스를 같이 배워야 한다.

 중간 정산 1 : 3 단계를 지나면, 지금까지는 '당연하다고 생각했던 것들'이 더 이상 당연한 것이 아니고, '자동으로 된다고 믿었던 것들'이 누군가에 의해 만들어진 것이라는 것을 이해하고 있다고 볼 수 있다. 또 3 단계를 넘고 나면, 이제 개발자로서 일단 늠름하게 일을 할 수 있는 수준이 되었다는 것을 의미한다.

4 단계 : 4 단계의 첫 번째 어려움은 알고리즘 그 자체이다. 효율적인 알고리즘은 제한적 자원인 컴퓨팅 파워와 메모리를 아끼기 위한 수학적, 논리적 절차이다. 최적의 알고리즘에 대한 욕구는 지구의 환경을 지켜야한다는 사해동포적인 공감력에 기반한다. 소프트웨어를 만들어내는 절차 상, 내가 만들어내는 모든 것이 최적일 필요는 전혀 없다. 또 모든 것의 답이 하나만 있는 것도 아니다. 하지만 '되는 것'이 우선 중요하고 '잘 되면' 더 좋고, '누가봐도 최선의 효율로 동작하면' 좋겠다는 간절함이 개발자에게 있어야 한다. 이 부분은 '학습 의지'가 필요한 부분이다. 이 의지의 약함이 4 단계의 첫번째 어려움이다.   

4 단계의 두 번째 어려움은 소위 말하는 패턴의 문제이다. 이 부분에 대하여 요즘에는 책도 많고, 여러 학교에서 과목을 개설하기도 한다. 문제는 패턴을 경험없이 사용하는 것이다. 가장 쉬운 예를 들어보자. 대개의 전공자들은 3 학년 정도에 운영체제를 배우면서 동기화 이슈를 접한다. Concurrency 라는 것의 본질은 위에서 극복한 1 단계 2 단계의 문제가 현실에서는 동시에, 다른 코드로, 같은 데이터에 대하여 벌어진다는 것이다. 수업에서는 동시성, 병렬성, Critical Section, Atomic Operation, Lock 등에 관한 설명, 동기화/데드락회피 방법을 배운다. 그리고 오직 책의 저자에게만 재미있고, 저자만 경험해 본 여러 연습 문제를 풀어본다. 대부분 학생은 그것이 왜 문제인지도 모를 가능성이 높고, 그 중에 어떤 학생은 답도 맞춘다. 4 단계의 두 번째 어려움은 경험적으로 이런 문제를 이해하는 과정이고, 그 경험을 바탕으로 예전에 풀려고 했던 (또는 풀기까지 했던) 연습 문제가 왜 문제인지를 이해하는 과정이다. 요즘에는 여러 프로그래밍 언어가 이 두 번째 어려움의 일부를 언어의 특성 또는 Primitive로 해결하고 있다. 하지만 개발자라면 이 부분에 대한 경험적 이해가 반드시 필요하다.

중간정산 2 : 4 단계를 극복한 사람을 '만렙' 개발자라고 부르고 싶다. 이들은 위대하다. 만세다.

5 단계 : 5 단계는 다시 데이터의 문제이다.  5 단계에서 데이터가 어렵다는 것은 2 단계 어려움과 전혀 다르다. 2 단계에서는 '사람이 생각하는 그 데이터'가 단위 데이터가 아니라는 점을 이해하기 어렵다는 것이고, 5 단계에서의 어려움은 세상의 모든 문제의 본질과 그 문제의 해결책이 데이터에서 기인한다는 것을 이해하는 것이다. 긴 말이 필요없다. 빅데이터, 머신 러닝이 요즘 가장 중요한 단어인 이유이고, 소프트웨어가 만들어내는 가치의 원천과 결과가 모두 데이터이기 때문이다. 데이터를 모아, 저장하고, 처리하고, 분석하여 문제의 핵심에 해당하는 Insight를 얻는 전 과정이 전혀 쉽지가 않다. 이 영역에서도 각종 툴들이 한 몫하기 때문에, 그 툴을 만드는 사람들과, Insight 영역에 집중하는 사람으로 분화되기도 한다.

5 단계의 어려움은 이전의 1,2,3,4 단계와는 달리 이제 소프트웨어의 영역을 넘어서는 뭔가가 필요하다는데 기인한다. 문사철/예술, 경제/경영, 수학/과학 등이 어려움의 전면에 있다. 답이 별로 없는 영역이다. 정말 열심히 공부하고, 경험을 쌓으면 제한적으로 통찰을 얻게 되는 것 같기는 하다. '정말 열심히'가 아니면, 잘 따라하는 척 하거나 포기하거나 이다. 

--

여기까지가 소프트웨어 개발자로 성장하는 다섯 단계와, 그 단계들이 어려운 이유이다. 다시 말하지만, 이 단계 구분은 '천재 개발자'에게는 해당이 안된다. 자기가 각 단계별 어려움을 크게 느끼지 못하고 5 단계를 넘어섰다고 생각되면 당신은 '천재 개발자'인 거다. 

* 정말 하늘에 감사해야하는 중요한 것은 어쨌거나 단계를 넘어 성장하는 과정이 자전거 타는 법을 배우는 것처럼, 몸에 남는다는 것이다. 한동안 안하다가 다시 소프트웨어를 해야하는 경우, 보통은 매뉴얼을 훑어 보는 것만으로 상당히 빠르게 예전의 감각을 찾을 수 있다. 

* 좋은 소프트웨어 교육이란 각 단계를 '충분한 경험을 쌓으면서' 올라설 수 있게 도와주는 것이다. 좋은 경험은 능동적으로 스스로의 문제를 만들고, 그 문제를 해결하는 과정을 옆 사람과 논의하고 비교하는 과정에서 쌓인다. 교육이라는 단어를 썼지만, 배움이라고 이해해야 하고, 배운다는 것은 스스로 문제를 해결해야 함을 의미한다. 

* 소프트웨어 개발의 길에 들어선 분들에게 행운이 있기를 기대한다.  

 

출처: 이민석 교수님 블로그 http://hl1itj.tistory.com/136?category=327240