더 공부할 것

이 책을 모두 읽었다면 컴퓨터의 다른 부분들에 대해서도 공부하고 싶어졌을 것입니다. 다른 언어에 대해 궁금해졌을 수도 있고, C 언어를 깊게 파 보고 싶기도 할 것입니다. 여러분을 위해 몇 가지 공부해봄직한 것들을 간단하게 소개하겠습니다. 추천 도서에서 원서는 의도적으로 배제하였습니다.


알고리즘 & 자료구조

알고리즘과 자료구조는 지금까지 배운 프로그래밍 언어에 수학을 도입하여 언어를 좀 더 효과적으로 사용할 수 있게 해줍니다. 좋은 알고리즘을 사용하면 같은 동작을 해도 더 효율적으로(적은 메모리 사용과 실행 시간) 작동합니다. 많은 언어들에서 기초적인 알고리즘과 자료구조를 제공하지만(대표적으로 C++의 STL), 구현이 되어 있지 않은 알고리즘도 많고, 또 이미 있는 것이라 해도 원리를 알고 사용하는 것과 그렇지 않은 채로 사용하는 것에는 큰 차이가 있기 때문에 한 번 쯤은 공부해 두는 것이 좋습니다.

알고리즘을 공부하고 싶다면 『알고리즘 문제 해결 전략』(구종만, 인사이트)를 추천합니다. 이 이외에 백준 온라인 저지(https://www.acmicpc.net) 등에서 알고리즘을 배우고 문제를 풀 수 있습니다. 이러한 온라인 알고리즘 트레이닝 사이트 사용에 팁을 조금 주자면, 실행 시간을 줄이겠다고 과도하게 스레드를 사용할 경우 일시적인 밴을 당할 수 있기 때문에 단일 스레드만을 사용하길 바랍니다.


컴퓨터 구조

이 언어 밑에서 어떤 작업들이 이루어지고 있는지, CPU는 어떻게 동작하는지 등을 알고 싶다면 컴퓨터 구조에 대해 공부하는 것이 좋습니다. 레지스터, 메모리, 캐시, 명령어 등에 대한 개념을 익히고 이를 코딩에 적용한다면 훨씬 효과적으로 움직이는 프로그램을 작성할 수 있을 것입니다. 컴퓨터 구조를 공부하고 싶다면 『컴퓨터 구조 및 설계』(David A. Patterson & John L. Hennessy, 한티미디어)나 『컴퓨터 시스템』(Randal E. Bryan & David R. O'Hallaron, 피어슨에듀케이션코리아)을 추천합니다. 다만 한 가지 말해두자면 학부 과정의 내용들을 담고 있으니 어렵다고 좌절하지는 마시기 바랍니다.


디자인 패턴

디자인 패턴은 오랫동안 연구되고 사용된 코드들의 패턴으로, 프로그램의 구조를 깔끔히 하는 데 도움이 됩니다. Builder, Visitor 등의 패턴이 있으며, 지금도 많은 디자인 패턴들이 만들어지고 있습니다. 디자인 패턴을 공부하면 오랜 시간 코딩해야만 얻을 수 있는 노하우들을 단기간에 얻을 수 있습니다.


C

만약 이 책을 읽은 후 자신이 C 언어를 마스터했다고 생각한다면 천만의 말씀, 만만의 콩떡입니다. '다루지 않은 것'에도 없는 C 언어의 수많은 기능과 그로부터 나온 수많은 꼼수들은 감히 그 전체 크기조차 헤아리기 쉽지 않습니다. 좀 더 심화적으로 C 언어를 공부하고 싶다면 『C 기초 플러스』(스티븐 프라타, 성안당)와 『이것이 C 언어다』(서현우, 한빛미디어)를 추천합니다. 이 이외에 Cpp Reference 등에서도 C 언어를 공부할 수 있습니다.


C++

C++은 1983년, 비아네 스트로스트룹에 의해 만들어진 언어로, C언어에 객체 지향 프로그래밍의 개념을 얹은 것입니다.

C++은 여러 차례의 개정을 거쳐 무척 크고 복잡한 언어가 되었습니다. C언어의 속도와 고급 언어들의 생산성 중 아무 것도 놓지 않았기 때문에 C++은 생산성 대비 속도를 생각해 보았을 때 아주 좋은 언어입니다. 특히 C++의 꽃이라 불리는 템플릿과 STL은 다른 언어에서는 찾아보기 힘든, C++의 자랑 중 하나입니다. 하지만 복잡한 문법들과 많은 기능들, 그리고 끊임없이 생겨나는 꼼수들 덕분에 C++에는 '평생 언어'라는, 웃을 수 없는 별명이 붙어 있습니다. 컴퓨터를 한계까지 쥐어짜 내고 싶은 사람이라면 배워봄직한 언어입니다.

C++은 게임이나 이미지 프로세싱, 압축 등 성능과 생산성 중 어느 것도 놓칠 수 없는 분야들에서 사용됩니다. 운영체제 쪽은 아직 C가 대부분이지만, 가끔씩 C++을 사용하기도 합니다. 꼭 C++로 전부 만들지 않더라도, 성능이 필요한 부분은 C++로 만들고 나머지 부분은 다른 고생산성 언어로 만들어 붙힐 수도 있습니다.

C++을 공부하고 싶다면 『C++ 기초 플러스』(스티븐 프라타, 성안당)와 『이것이 C++이다』(최호성, 한빛미디어)를 추천합니다. 이 이외에 Cpp ReferenceC plus plus, MSDN C++ 언어 참조등에서도 C++을 공부할 수 있습니다.


Ruby

Ruby는 1995년, 마츠모토 유키히로(Ruby 사용자 사이에서는 '마츠'라는 별명으로 불립니다)에 의해 만들어진 언어로, C/C++과는 다르게 컴파일러 대신 인터프리터를 사용합니다. 인터프리터를 사용하면 컴파일러를 사용할 때 보다 쉽게 프로그램을 수정할 수 있지만, 속도 면에서는 컴파일러를 사용하는 것보다 조금 느릴 수 있습니다. 루비는 2.6.0 버전부터 JIT 컴파일을 지원하기 때문에 다른 스크립트 언어들에 비하면 속도가 빠른 편입니다.

C++가 C언어에 객체 지향 프로그래밍의 개념을 얹은 것이라면, Ruby는 처음부터 객체 지향 프로그래밍 언어로 설계되었습니다. 따라서 문법도 간단하며, 언어 자체를 익히는 것은 C 언어보다 훨씬 쉽습니다. 이미 아는 언어가 있다면 무척 빠르게 익힐 수 있겠지요. 하지만 Ruby는 하드웨어로부터 멀리 떨어진, 다시 말해 고도로 추상화 된 언어이기 때문에 Ruby만으로 컴퓨터를 깊게 익히기는 힘듭니다.

C/C++가 운영체제와 게임 등 성능이 필요한 분야에서 주로 사용되는 데 비해, Ruby는 생산성이 중요시되는 곳에서 주로 사용됩니다. '속도는 모르겠고 일단 띄우고 본다'라는 의미지요. 특히 Ruby on Rails와 함께 웹 개발에서 인기가 많습니다. 비슷한 목적을 가진 언어로는 Python, Lua 등이 있으나, 객체 지향 프로그래밍을 잘 익히고 싶다면 Ruby를 배울 것을 추천합니다. 물론 위의 두 언어도 객체 지향 언어입니다.

Ruby를 공부하고 싶다면 『프로그래밍 루비』(데이브 토머스 & 채드 파울러 & 앤디 헌트, 인사이트)를 추천합니다. 이 이외에 루비 한국어 문서에서도 루비의 간단한 기능들을 학습할 수 있습니다.


C#

이름에서 알 수 있듯, C#은 C 언어로부터 파생된 언어입니다. 2000년, 마이크로소프트에서 개발되었으며, C++++에서 ++++를 적절한 모양으로 배치해 #이 되었다고 합니다.

C++이 C에 객체 지향을 그대로 얹어놓은 것이라면 C#은 Java처럼 적극적으로 객체 지향을 도입하였습니다. C++보다 쉽다는 평가를 얻고 있지만, 최근 들어 기능이 많이 추가됨에 따라 난이도가 상승중인 언어입니다.

C#은 독특한 컴파일 방식을 가지고 있습니다. 이를 알기 위해서는 컴파일러의 구조를 약간 알아야 합니다. 컴파일러는 대개 프론트엔드 - 미들엔드(옵티마이저) - 백엔드의 구성을 갖고 있습니다. 이러한 구조를 갖게 되면 언어의 수와 아키텍처 수의 곱만큼 컴파일러가 필요하게 됩니다. 이를 해결하는 방법은 고급 언어와 기계어 사이의 중간 언어를 만드는 것입니다. 컴파일러는 고급 언어를 중간 언어로 번역하고, 가상 머신은 중간 언어를 기계어로 번역합니다. 이러한 구조를 취하게 되면 언어가 1개 추가되어도 1개의 프론트엔드 컴파일러만이 더 필요하고, 아키텍쳐가 1개 추가되어도 1개의 백엔드 컴파일러만이 필요합니다. 물론 네이티브 기계어로 번역하는 것보다는 실행 속도가 느리지만, 컴파일러를 만드는 데 필요한 노력이나 이식성 등을 생각해 보면 이 정도의 속도 손실은 감안해야 합니다. 최근에는 JIT 컴파일을 도입하여 속도를 향상시키는 추세입니다. 이러한 구조는 JVM(Java, Kotlin, Scala, Clojure 등), .NET Framework(C#, Visual Basic .NET 등), LLVM(Clang C++, Swift 등)에서 볼 수 있습니다.

C#이 사용하는 가상머신은 .NET Framework입니다. C#의 컴파일러는 CIR 코드를 내놓고, 이는 .NET CLR에 의해 기계어로 변환됩니다. .NET 프레임워크를 사용하는 다른 언어에는 VB .NET, C++ .NET 등이 있습니다.

C#은 마이크로소프트에서 만든 언어답게 Windows용 프로그래밍 제작에 특화되어 있습니다. 하지만 요즘, C#을 Windows가 아닌 다른 플랫폼에서도 사용할 수 있게 하려는 시도들이 있으니 기대해 볼 만 합니다. 또, C#만으로는 속도가 모자랄 때, 속도가 필요한 부분은 C++로 만들고, 나머지 부분들은 C#으로 만드는 방법은 요즘 큰 인기를 얻고 있는 프로그래밍 방법 중 하나입니다.


Swift

Swift는 2014년, 애플에서 개발한 프로그래밍 언어로, 기존의 Objective-C를 대체해 OS X, iOS용 프로그래밍 언어로 사용됩니다. 애플 기기용 앱을 만들고 싶다면 반드시 익혀야 하는 언어입니다.

Swift는 LLVM 위에서 실행되는데, 가상 머신 위에서 돌아가는 다른 언어들과는 다르게 IR(LLVM 중간 언어)와 Swift 코드 사이에 중간 언어가 하나 더 있습니다. 이를 통해 Swift는 많은 최적화 기회를 얻습니다.

현재는 애플 기기용으로밖에 사용하지 못하지만 곧 Windows와 Android에서도 사용 가능해질 예정입니다.


Kotlin

Kotlin은 2011년, JetBrains에서 개발한 언어로, JVM에서 돌아갑니다. LLVM을 사용한 컴파일 또한 지원합니다.

Kotlin은 Java보다 간단한 문법들과 고급 기능들을 가지고 있어 큰 인기를 얻고 있습니다. 또 기존의 Java 프로그래머들이 배우기 쉽다는 점 덕분에 벌써 많은 회사가 Kotlin을 도입했습니다. 2017년에는 구글 Android의 공식 언어로 지정되기도 하여 앞으로도 상승세일 예정입니다.


Lisp

Lisp는 1958년, 존 매카시가 개발한 프로그래밍 언어로, FORTRAN 다음으로 오래된 언어입니다. 사실 Lisp는 어느 한 언어만을 이야기한다기 보다는 표준인 Common Lisp와 그 사투리들(Scheme, Clojure, Emacs Lisp 등)을 모두 가리키는 표현입니다(Lisp-family). 다른 언어들이 여러 가지 괄호를 사용하는 데 비해 Lisp에서는 오직 ()만을 사용합니다. 또, Lisp에서는 사칙 연산 같은 모든 것이 함수로 취급되며, 때문에 리스프 코드를 보면 괄호가 무척 많습니다. 예를 들어 3 * 15 + 20 / 10과 같은 간단한 식도 리스프에서는 (+ (* 3 15) (/ 20 10))라고 씁니다.

이름에서 알 수 있듯 리스트를 다루기 쉬우며 함수를 일급 객체로 취급한다는 점, 그리고 코드와 데이터를 자유롭게 바꿀 수 있고 eval 함수가 존재한다는 점 등 덕분에 메타 프로그래밍이 쉬우며, 인공지능 같은 분야에 주로 사용됩니다. 그 이외에 AutoCAD나 Emacs 등에도 사용됩니다.

당시로서는 혁신적이었던 프로그래밍 개념인 Garbage Collection이나 JIT 등을 도입했으며, 이는 현대의 다른 프로그래밍 언어들에도 영향을 주었습니다.


Haskell

Haskell은 1997년 개발된 순수 함수형 프로그래밍 언어로, 앞에서 소개한 다른 언어들과는 다른, 커링, 느긋한 계산 등의 특징들을 갖고 있습니다.

기존의 프로그래밍 언어들은 변수와 조건 분기를 사용합니다. 즉, 튜링 머신에 그 근간을 두고 있습니다. 하지만 Haskell과 같은 순수 함수형 프로그래밍 언어들은 이것들을 사용하지 않고, 람다 대수를 사용합니다. 이 둘은 동치임이 수학적으로 증명되어 있습니다.

이러한 프로그래밍 언어에서는 변수를 사용하지 않기 때문에 모든 함수는 상태를 갖지 않는, 순수한 수학의 함수이고(이를 참조 투명성이라 합니다), 명령어들의 순서는 아무런 의미를 갖지 않습니다. 원칙적으로는 말입니다. 실제로는 I/O를 위해 약간의 Side Effect가 필요합니다.

이러한 참조 투명성으로 인해 순수 함수형 언어들은 병렬 작업(멀티 스레딩)이 쉽습니다. 단일 코어의 성능을 올리기 힘든 요즘, 순수 함수형 언어들이 다시 주목받고 있습니다.

Haskell의 다른 특징에는 타입 클래스와 모나드가 있습니다. 타입 클래스는 타입 변수를 사용해 한 타입을 인자로 받아 다른 타입을 내보내는 것으로, C++의 template과 비슷합니다. 또, 이 타입 변수에 들어갈 수 있는 타입들을 제한할 수도 있습니다. 모나드는 범주론의 개념으로, '내부 함자 범주의 모노이드 대상'으로 정의되어 있습니다. 물론 이렇게 써 놓으면 알아볼 수도 없을 뿐만 아니라 프로그래밍에도 도입할 수 없기 때문에, Haskell에서 실제로 사용하는 모나드는 조금 다릅니다.

아까 말했듯, Haskell의 모든 함수는 상태(statement)를 갖지 않는, 순수한(pure) 함수입니다. 순서에 의미가 없다고 했으니, I/O 작업은 불가능하겠지요. 그런데, 여기서 함수의 인자 중에 statement가 있고 함수의 반환값이 statement에 대한 정보를 포함하고 있다면 어떻게 될까요? 좀 더 정확히 말하자면, 함수가 상태와 결합하는 것입니다. 지금까지 말한 것을 종합하자면, Haskell에서는 함수가 statement를 받고 statement를 뱉는 과정을 반복하며 함수의 순차적 시행을 흉내 냅니다. 하지만 여전히 함수는 순수하지요.

사실 모나드는 I/O를 위해 만들어진 것으로, 초기 Haskell에는 존재하지 않았습니다. 따라서 Haskell을 공부하기 위해 반드시 모나드를 익힐 필요도 없고, do같은 문법으로 좀 더 쉽게 순차적 시행을 할 수도 있습니다. 너무 겁먹지는 말고, 한 번 공부해 보는 것도 나쁘지 않습니다.

  

Rust

Rust는 2015년, 모질라 재단에서 개발한 언어로, 현재의 C++를 대체하려 하고 있습니다. Rust는 Garbage Collection 없이 메모리 안전성을 제공합니다. 이는 값의 대입이 소유권의 이전을 의미하게 함으로써 달성합니다. 즉, 값은 이름에 종속적이며, 컴파일 타임에 소유권의 모든 이전을 추적할 수 있습니다. 또, Rust에서 변수는 기본적으로 불변, 즉 수정이 불가능한데, 이렇게 불변을 권장하고 공유를 금지함으로써 Rust는 멀티 스레딩에서 큰 이점을 갖고 있습니다.

Rust는 아직 신생 언어이지만, 그 독특한 설계 덕분에 2017년 Stack Overflow 설문조사에서 선호 언어 1위를 하는 등 큰 인기를 끌고 있습니다.


HTML

HTML은 마크업 언어로, 웹 페이지를 만들 때 사용합니다. 웹 페이지를 만드는 데 관심이 있다면 반드시 알아야 하는 것 중 하나입니다.


Linux

Linux는 컴퓨터 커널의 일종으로, 이를 사용해 만든 운영체제들을 GNU/Linux라 합니다. 이들 운영체제는 원한다면 자유롭게 수정해 사용할 수 있습니다.

Windows와 구분되는 GNU/Linux만의 가장 큰 특징은 바로 CLI입니다. 물론 Windows에서도 cmd를 사용하여 비슷한 작업이 가능하지만, 수준이나 편의성을 생각해 보았을 때 GNU/Linux 쪽의 bash쪽이 훨씬 낫습니다. 또한, 많은 개발 환경들이 Linux 전용으로 만들어져 있기 때문에, 본격적인 개발을 하고 싶다면 Linux를 배우는 것도 좋다고 생각합니다.


WinAPI

WinAPI는 C언어를 위한 Windows용 API로, 하드웨어나 메시지, 커널 등에 관련된 사항들을 쉽게 처리할 수 있게 도와줍니다. Windows용 프로그램을 만들기 위해서는 반드시 알아야 하는 것의 하나입니다.