이 글은 2016년 11월 16일 서울 엘릭서 밋업에서 한 발표의 내용을 정리한 것입니다.

초심자에게 가르칠 언어를 선택할 때 바로 엘릭서를 떠올리실 분은 없을 것입니다. 파이썬, 루비, 자바스크립트, C/C++, 자바 등이 더 일반적이죠. 하지만 저는 엘릭서 특유의 장점 덕분에 엘릭서도 첫 언어로 진지하게 고려해볼 만하다고 생각합니다.

프로그래밍을 배우는 것은 정말 어렵다

숙련된 개발자는 초심자가 프로그래밍을 배우는 것이 얼마나 어려운지 잘 모릅니다. 자신이 지금까지 수많은 어려움을 이겨내왔다는 것을 대부분 벌써 잊었기 때문이죠. 하지만 초심자에게 프로그래밍을 가르쳐 보면 너무나 당연하다고 생각한 것들이 초심자에게는 얼마나 큰 장벽으로 다가오는지 알 수 있습니다.

프로그래밍을 하기 위해서는 정말 많은 사전 지식과 훈련이 필요합니다. 어떤 초심자들은 독수리 타법으로도 타이핑을 힘들어하기도 하고, 어떤 이들은 장문의 글을 읽고 이해하는 경험 자체가 적어서 이를 어려워 합니다. 초심자들은 이런 낯설고 어려운 환경에서 어려운 개념들을 새로 배워나가야 합니다.

프로그래밍을 배우는 것은 그래서 정말 어렵습니다. 이 사실을 잊지 말아야 합니다.

절차형이나 객체지향 프로그래밍은 초심자가 배우기에는 적절하지 않다

어떤 패러다임이 기술적으로 혹은 개념적으로 더 우수하다는 말이 아니라, 교육과 학습이라는 측면에서 보았을 때 더 낫다는 말입니다.

어려운 주제를 가르칠 때 가장 중요한 것은 어려운 부분을 잘게 쪼갠 다음 시간을 들여 가르치는 것입니다. 그래야만 학생들이 어려운 주제에 압도되지 않습니다. 이미 잔뜩 긴장하고 주눅들어 있는 초심자들에겐 더더욱 중요한 일입니다.

학생들이 일반적으로 배우는 절차형 프로그래밍이나 객체지향 프로그래밍에서는 학습 난이도와 속도를 조정하기 어렵습니다.

제가 경험한 바로는 변수, 상수, 함수 등의 기본 개념은 대부분의 학생들이 큰 문제 없이 이해할 수 있습니다. =가 무슨 의미를 가지는지 등은 금방 이해하죠. 물론 그게 할당인지 바인딩이지 같이 구체적인 것은 이 단계에서는 가르치지 않습니다.

절차형 언어 가르치기

문제는 그 다음 단계에서 발생합니다. 절차형 언어는 로우 레벨을 지향하기 때문에 포인터와 메모리 위치 등의 개념을 다룹니다. 그리고 그런 개념을 설명하기 위해서는 수업 내용에 하드웨어가 들어가게 됩니다.

하드웨어와 소프트웨어는 관계는 있지만 결국 별개의 주제입니다. 학생들은 이 두 가지 분야를 동시에 배울 뿐 아니라, 하드웨어와 소프트웨어가 어떻게 상호작용 하는지도 배워야만 합니다. 그 결과 학습 난이도가 매우 가파르게 상승합니다. 이렇게 보면 포인터를 배우는 시점에서 수많은 학생들이 수강을 포기하는 것은 오히려 당연한 일입니다.

이런 문제는 보통 어려운 개념을 작은 부분으로 쪼개어 가르쳐 해결합니다. 하지만 포인터를 가르칠 때는 그런 방법을 사용하기 어려운데, 포인터가 무엇인지 설명하려면 메모리에 대해서 이야기할 수 밖에 없기 때문입니다. 즉, 여러가지 주제가 정말 긴밀히 연결되어 있기 때문에 쪼개서 가르치는 것이 사실상 불가능합니다.

저는 절차형 프로그래밍은 다른 방법으로 가르쳐야 한다고 봅니다. 하드웨어나 소프트웨어 중 하나를 먼저 배우도록 하고, 그 뒤에 절차형 프로그래밍을 배우도록 해서 상대적으로 부족한 부분을 보충하도록 해야 합니다.

먼저 하드웨어에 대해서 공부하고 그 뒤에 절차형 언어를 배우는 것은 전통적인 전기 컴퓨터 공학 교육과정과 동일합니다. 소프트웨어를 먼저 배우는 것은 소프트웨어 개발 쪽에 더 가까운데, 이 때는 함수형이나 객체지향 프로그래밍을 통해 배우는 것이 더 낫습니다. 앞서 말했듯이 절차형 프로그래밍을 배우려면 하드웨어를 반드시 수업내용에 포함시켜야 하기 때문입니다.

이 글의 주제는 프로그래밍을 배우는 것이기 때문에 후자만을 고려하겠습니다. 다음으로는 객체지향 프로그래밍과 함수형 프로그래밍을 살펴보겠습니다.

객체지향 프로그래밍 가르치기

객체지향 프로그래밍에는 다른 문제가 있습니다. 바로 객체입니다. 객체란 개념은 추상화 수준이 너무 높은데도 불구하고 교육과정에서는 너무 앞부분에서 배우게 됩니다.

위키피디아를 보면 “객체는 변수, 데이터 구조, 함수나 메서드 등일 수 있으며, 또한 값을 가진 메모리 주소로써 식별자를 통해 참조될 수 있다”고 합니다.

이 정의에서 객체가 무엇인지 이해하기 위해서는 얼마나 많은 기반 개념을 이해하고 있어야 할까요? 세어 보자면 변수, 데이터 구조, 함수, 메모리 주소, 값, 참조, 식별자 총 7개의 개념에, 이를 바탕으로 추상화하는 과정까지 필요합니다.

당장 이번 달에 프로그래밍을 시작한 사람들이 이런 개념을 이해하길 바라는 것은 말도 안 됩니다. 하지만 객체는 객체지향 프로그래밍의 기본 단위이기 때문에 코드를 작성하는 단계 이전에 반드시 배워야만 합니다. 생략하는 것도, 교육과정 뒷 부분으로 미루는 것도 불가능합니다.

유일한 방법은 원래 개념의 상당 부분을 생략해서 단순화시켜 가르치는 것 뿐입니다. “객체는 사물”이라거나 “객체는 명사”라거나 “객체는 클래스의 인스턴스” 등의 보다 간단한 정의가 이런 과정에서 나왔다고 봅니다.

그런데 앨런 케이가 객체라는 개념을 만들 때 가졌던 생각과 이를 비교해봅시다. “객체는 생물학적인 세포나 네트워크 상의 각 컴퓨터처럼 서로 메시지를 통해서만 소통할 수 있는 무엇이라고 생각했습니다.” 전 문단의 정의와 비교해보면 추상화의 수준에서 아찔할 정도로 차이가 납니다.

자주 쓰이는 소프트웨어 관련 용어를 사용하자면 이런 단기적인 접근법은 “교육 부채”를 발생시킵니다. 완전한 개념의 객체를 염두에 두고 만들어진 객체지향 프로그래밍이라는 패러다임 안에다가 단순화된 개념의 객체를 사용하려 하면 무엇인가 잘 맞아 떨어지지 않습니다. 저를 비롯한 수많은 초보 개발자가 이로 인해 어려움을 겪어왔습니다.

객체지향 프로그래밍을 어떻게 하면 초심자에게 온전히 가르칠 수 있을지는 저도 잘 모르겠습니다. 객체라는 개념 자체가 탄탄한 배경지식 없이는 너무나 이해하기 어려운 개념이기 때문입니다.

엘릭서 가르치기

엘릭서는 함수형 언어기 때문에 하드웨어를 직접 다룰 필요가 없습니다. 또한 객체보다 훨씬 가르치고 배우기 쉬운 함수를 코드의 기본 단위로 사용합니다.

다른 함수형 언어에 비하면 엘릭서는 간단한 편입니다. 모나드, 타입 클래스, 커링 등의 난해한 개념을 사용하지 않고 거의 항상 평범한 함수만 사용합니다.

이는 첫 언어로 엘릭서를 가르친다고 했을 때 가장 가치 있는 특징이 될 것이라고 봅니다. 엘릭서에서는 코드를 작성할 때 추상화 수준이 재귀적으로 더 증가하는 타입 클래스나 모나드 같은 것을 만들지 않고 간단한 함수를 조합하고 연결합니다.

이렇게 단일한 추상적 개념을 사용하면 두 가지 장점이 있는데, 학생들은 함수 하나에만 집중해서 이를 조합하는 다양한 방법을 단계적으로 배워나갈 수 있고, 교사들은 비슷한 난이도를 가진 여러 개념을 배우는 순서나 기간을 훨씬 자유롭게 교육계획에 반영할 수 있습니다.

게다가 모나드나 매크로 같은 고급 개념을 나중에 충분히 배울 수도 있죠.

또한 엘릭서의 몇몇 특징 덕분에 보다 쉽게 배울 수 있습니다. 예를 들어 파이프 오퍼레이터는 함수의 조합(function composition)을 좌에서 우로 작성할 수 있도록 해줍니다. 이 방식은 이미 좌에서 우로 표기하는 언어를 사용하는 사람들에게는 다른 표기법에 비해 훨씬 직관적입니다. 엘릭서에서 사용하는 파이프 오퍼레이터는 코드를 읽을 때 시선의 움직임을 그대로 따라가기 때문에 개인적으로 특히 좋아합니다.

foo(bar(baz(new_function(other_function()))))

other_function() |> new_function() |> baz() |> bar() |> foo()

other_function() 
|> new_function() 
|> baz() 
|> bar() 
|> foo()

동적 타입 시스템도 도움이 됩니다. 엘릭서에 있는 타입과 그 특징을 모두 꿰뚫고 있지 않아도 코드를 일단 작성할 수 있게 해주기 때문입니다. 타입 추정 시스템이 잘 되어 있다면 정적 타입 시스템도 나쁘지 않지만, 그래도 동적 시스템이 더 접근하기 쉽긴 합니다.

또한 엘릭서는 생산성을 강조하는 언어입니다. 여기서 제가 의도한 의미는 타이핑을 조금만 해도 피드백을 받고 무엇인가를 만들어 낼 수 있다는 뜻입니다. 덕분에 학생들은 빠른 피드백을 받을 수 있을 뿐 아니라, 친구나 가족에게 보여줄 수 있는 어플리케이션을 금방 작성할 수 있게 됩니다. 이는 학생들에게 동기를 부여하기 때문에 매우 유용합니다.

물론 엘릭서라는 언어에도 독특하고 이상한 부분이 있습니다. 예를 들어 char list, binary, string은 매우 이상합니다. [69, 108, 105, 120, 105, 114]를 입력했는데 'Elixir'라는 결과가 나오는 것은 직관적이지 않죠. OTP를 이해하는 것도 객체라는 개념을 이해하는 것만큼이나 어렵습니다. 게다가 엘릭서의 기반에는 얼랭/OTP라는 거대한 개념이 숨겨져 있습니다. 하지만 그럼에도 불구하고 저는 엘릭서라는 언어가 교육용으로 매우 유용할 수 있다고 봅니다.

1부 요약

  1. 초심자가 프로그래밍을 배우는 것은 매우 어렵다.
  2. 교사가 학습 난이도와 속도를 조정할 수 있는 것이 매우 중요하다.
  3. 절차형 프로그래밍이나 객체지향 프로그래밍에서는 배워야 하는 필수 개념 때문에 학습 난이도와 속도를 조정하기 어렵다.
  4. 엘릭서는 다른 함수형 언어보다 훨씬 간단하고 생산성도 높다.