2019-11-13 작성

[Book] 프로그래밍 언어도감

마스이 토시카츠 / 영진닷컴 / 2018.08.01


프로그래밍 언어도감?

도서관에서 제목을 보고 눈에 띄어 빌리게 된 책이다. 수백개의 프로그래밍 언어 중에서 사람들에게 인기 있는 67개를 선별하여 각 언어의 특징과 기능을 간단히 소개하고 있다. 

저자가 언어를 선별한 기준은 사용자가 간단하게 실행할 수 있어야 하고, 많은 사람들이 사용하고 있어야 한다는 기준으로 골랐다고 한다.

[프로그래밍 언어 목록]

Assembly language, ActionScript, Ada, AWK, Bash, BASIC, bc, Brainfuck, C, C#, C++, CLIPS, Clojure, COBOL, CoffeeScript, csh, D, Dart, Elixir, Erlang, F#, Factor, Fantom, Forth, Fortran, Go, Groovy, Haskell, Icon, Intercal, Java, JavaScript, Julia, Kotlin, LISP, Lua, Nemerle, Nice, Nim, Objective-C, OCaml, Octave, Oz, Pascal, Perl, PHP, Pike, PL/I, PostScript, Prolog, Python, R, Racket, Ruby, Rust, Scala, Scheme, Scratch, sed, Smalltalk, SQL, Swift, Tcl, TypeScript, Unlambda, Visual Basic, Whitespace


아래는 JavaScript 언어를 다루는 부분이다. 한눈에 봐도 그림과 여백을 활용해서 무겁지 않은 느낌이다. 한 장 분량에 한 개의 프로그래밍 언어에 대해 다루기 때문에, 깊은 지식을 얻기보다는 각 언어의 핵심 키워드를 통해 대략적인 감을 잡을 수 있도록 가이드한다.

 

책을 보면서 재미있었던 부분은 '하노이의 탑' 예제를 67개의 언어로 구현했다는 점이다. 아래는 무려 SQL문(!?)으로 하노이의 탑을 구현한 모습이다. 


특히 Brainfuck이라는 언어로
구현한 하노이의 탑 예제가 굉장히 인상 깊었다. Brainfuck은 +, -같은 8개의 명령 만으로 소스코드를 짤 수 있다고 한다.


책을 읽으면서 아쉬웠던 점은,

  • 언어 도감이다 보니 단순한 알파벳 순으로 언어가 나열되었다는 점이다. 언어들이 연관된 흐름으로 구성되지 않아서 읽으면서도 흐름의 맥이 끊기는 느낌이 들었다.
  • 하노이의 탑 예제로 언어 간의 문법을 비교하는 것도 좋았지만, 좀 더 와 닿는 다른 표현 방식이 있지 않았을까? 실생활 서비스에 어떻게 적용되었는지 구체적인 예시가 있으면 언어의 핵심가치가 무엇인지 이해하기 쉬웠을 것 같다. 

반대로 도움이 된 부분이 있었다. 바로 책의 앞장과 뒷장이었다.

  • 앞장에서는 프로그래밍 언어의 특징과 역사를 다루면서 프로그래밍 언어를 선택하는 기준에 대해 언급하고 있다.
  • 뒷장에서는 언어를 선택할 때 고려해야 할 점들(개발 환경, 실행 환경, 구현 기법 등)과 기본적인 프로그래밍 지식을 설명하고 있는데, 특히 알고리즘의 중요성을 설명하고 있다. 프로그래밍 언어는 계속 새롭게 등장하고 있지만, 대표적인 알고리즘은 한 번 마스터하면 오래 쓸 수 있다. 저자의 의도는 알고리즘의 중요성을 알리고 적재적소에 사용할 수 있게 다양한 언어를 설명하고 싶었던 것으로 보인다.

아래는 앞장과 뒷장의 내용을 일부 요약한 내용이다. 

앞장

어떤 프로그래밍 언어를 선택할까

  • 만들고 싶은 내용이 결정되면 구현 가능한 언어의 수는 어느 정도 추려낼 수 있다.
  • Windows 데스크톱 애플리케이션을 만들고 싶다면 : C#
  • iPhone 애플리케이션을 만들고 싶다면 : Objective-C, Swift
  • 렌털 서버에서 동작시키는 웹 애프리케이션이라면 : PHP, Perl
  • Excel 처리를 자동화하고 싶다면 : VBA 등

다양한 프로그래밍 언어가 존재하는 이유

  • 각 프로그래밍 언어에는 개발자의 바람이 담겨있다.
  • 일반적으로 나중에 등장한 언어가 기능 및 성능 면에서 향상된 경우가 많다.
  • 다양한 프로그래밍을 알고 있으면 보다 좋은 선택지를 발견할 가능성이 높다.

프로그래밍 언어를 선택하는 기준

프로그래밍 언어의 분류

  • 처리계에 다른 분류 : 컴파일러, 인터프리터, JIT 컴파일러, 트랜스파일러
  • 패러다임에 따른 분류 : 절차형, 객체지향형, 함수형, 논리형

샘플 프로그램 동작시키기

뒷장

개발 환경과 실행 환경 

  • 텍스트 에디터 : Emacs, Vi, Atom, Sublime text, Visual Studio Code
  • 통합 개발 환경 : Visual Studio, Xcode, Eclipse, IntelliJ IDEA

빌드와 배포

  • 빌드 : 일반적으로 컴파일 실행이나 라이브러리를 링크해서 패키지화 하는 단계
  • 배포 : 웹 애플리케이션을 이용 가능한 환경에 올려두는 것
  • 빌드 툴 : GNU Make, Ant, Maven, Gradle, Bazel

테스트 툴과 도큐먼트 생성

  • 가능한 자동화된 방식으로 test를 하기 위해 테스트 툴이 사용된다.
    • 유닛 테스트 자동화 툴 : xUnit
    • Java 테스트 툴 : JUnit
    • PHP 테스트 툴 : PHPUnit
    • Python 테스트 툴 : PyUnit
    • 계속적으로 빌드, 테스트, 배포 등의 처리를 자동화 하는 툴 : Jenkins
  • 문서의 생성을 자동화
    • Java용 : JavaDoc
    • .NET용 : DocFx
    • PHP용 : phpDocumentor
    • Doxygen

프레임워크와 패키지 매니저

  • 프레임워크
    • PHP : CakePHP, Laravel
    • Ruby : Ruby on Rails
  • 패키지 매니저
    • 자동적으로 최신 버전을 체크하거나 갱신 및 삭제도 가능한 툴
    • PHP : Composer
    • .NET : NuGet
    • Ruby : RubyGems

표기법

  • 중위 표기법은 사람이 알기 쉽지만, 컴퓨터로 처리하는 경우 연산자 우선순위를 고려해서 실행하므로 번거롭다. 
  • 중위 표기법
    • 1+2*3
    • (1+2)*3
  • 전위 표기법 : 폴란드 표기법 (예시 : LISP)
    • +1*23
    • *+123
  • 후위 표기법 : 역 폴란드 표기법 (예시: Forth, PostScript)
    • 123*+
    • 12+3*

GC에 의한 메모리 관리

  • 메모리 누수를 방지하기 위해, 사용되지 않는 메모리를 자동적으로 해방하는 'GC' 기능이 있다.
  • 단, GC가 동작하는 타이밍은 일반적으로 프로그래머가 제어할 수 없다.

병렬 처리와 병행 처리

  • 프로세스 : OS의 시점에서 본 실행의 단위
  • 스레드 : 1개의 프로세스 안에서의 처리 단위
  • 1개의 프로세스 안에서 복수의 스레드가 동작할 수 있다.
  • 병렬(Parallel) : 복수의 처리를 동시에 행하는 것
    • 복수의 cpu가 필수
  • 병행(Concurrent) : 겉보기에 복수의 처리를 동시에 행하는 것
    • 복수의 처리를 잘게 쪼개서 바꾸어 넣어가면서 실행하는 것으로, 겉보기에는 동시에 실행하고 있는 것처럼 보인다. 소프트웨어 개발에서 중요한 것은 병행 처리이다.
    • 병행 처리의 구현은 프로그래밍 언어에 따라서 크게 다르다.

AST, LLVM, Clang

  • 어휘 분석: 소스코드에 사용된 문자를 읽어들여 의미가 있는 문자열로 인식하는 단계. (예시: Lex, Flex) 
  • 구문 분석(파서): 어휘 분석한 결과를 받아서, 그 기술이 언어의 문법으로 문제가 없는지를 판단한다. (예시: Yacc, Bison, LL 파서)
  • 코드 생성: 구문 분석 결과에 따라 실행용 코드를 생성해, 런타임에서 실행 or 인터프리터 형식으로 실행한다.
    • AST : 구문 분석한 결과를 트리 구조로 분석해, AST 표현을 이용하는 언어가 늘고 있다. 
    • LLVM : 임의의 프로그래밍 언어에 대응 가능한 컴파일러 기반이 되는 기술.
    • Clang : LLVM을 백엔드로 활용한 프론트엔드로, C, C++, Objective-C 등을 위한 Clang이 있다.

정적 타이핑, 동적 타이핑

  • 자료형을 컴파일 시에 판단할지, 실행 시에 판단할지에 따라 구분된다.
  • 정적 타이핑: 실행 전에 이미 자료형이 정해져 있는 언어
    • 처리를 빠르게 실행 가능
    • 프로그래머의 인위적 실수를 방지
  • 동적 타이핑: 실행 중에 그 변수가 사용될 때 변수의 자료형이 정해지거나 변하는 언어
    • 많은 스크립트 언어는 동적 타이핑을 채용하고 있다.
    • 동적 타이핑 언어라면 자동 형변환이 이루어지는 경우도 있다.

값과 참조형

  • 기본형과 참조형이 상호 변화할 경우 : 박싱, 언박싱
  • int price = 12345;
  • Integer total = new Integer(price); // 박싱
  • int val = total.intValue(); // 언박싱

Lisp-1, List-2

  • 함수형 언어의 경우, 함수의 인자로서 함수를 넘겨주는 등 함수와 변수의 구별이 애매해지는 경우가 있다.
  • Lisp-1
    • 함수와 변수의 네임스페이스가 분리되어 있지 않은 방식(네임스페이스가 1개 밖에 없음)
    • Scheme, JavaScript, Python
  • Lisp-2
    • 함수와 변수의 네임스페이스가 복수로 분리되어 있는 방식
    • Common Lisp, Ruby, Smalltalk

알고리즘은 변하지 않는다.

  • 대표적인 알고리즘은 한 번 마스터하면 오래 쓸 수 있다.
  • 하드웨어 속도가빨라지고 충분한 양의 메모리를 탑재할 수 있는 환경에서는 언어의 차이로 고민하기 보다 알고리즘을 바꾸는 것으로 압도적으로 빨라지는 경우도 많다.

좀 더 읽어보기