작가의 말
동시성은 어디서나 존재한다. 시장에 다중코어 프로세서가 늘어나면서, 동시 프로그래밍의 필요성이 개발자 사회를 강타했다. 한때 동시 프로그래밍은 프로그램과 시스템의 비동기성을 표현하기 위해 쓰였으며, 주로 학술적인 분야에 한정됐지만, 이제는 소프트웨어 개발에서 널리 사용 중인 방법론 중 하나가 됐다. 그 결과, 고급 동시성 프레임워크와 라이브러리가 놀라운 속도로 생겨나고 있다. 최근 몇 년은 동시 프로그래밍의 르네상스라 할 수 있다.
최근의 언어와 동시성 프레임워크에서 추상화의 정도가 점점 높아짐에 따라, 이들을 언제, 어떻게 사용할지 알아두는 것이 점점 중요해지고 있다. 스레드(thread), 락(lock), 모니터(monitor) 등의 전통적인 동시성과 동기화 기본 요소를 잘 알아두는 것만으로는 더 이상 충분하지 않다. 전통적인 여러 동시성 문제를 해결하면서, 특정 목표를 잘 달성하기 위해 만들어진 고수준 동시성 프레임워크들이 점점 동시 프로그래밍 세계를 장악하고 있다.
이 책은 스칼라에서 고수준 동시 프로그래밍을 설명한다. 또한 다양한 동시성 주제를 자세히 설명하고, 동시 프로그래밍의 기본 이론을 다룬다. 그와 동시에, 최신 동시성 프레임워크를 설명하고, 자세한 의미를 알려주며, 사용법을 독자에게 가르쳐준다. 이 책의 목표는 중요한 동시성 추상화를 소개하는 동시에 실제 코드에서 추상화가 어떻게 쓰이는지 보여주는 것이다.
독자 여러분이 이 책을 읽고 나서 동시 프로그래밍을 이론적으로 잘 이해하는 동시에, 올바르고 효율적인 동시 프로그램을 작성하는 데 필요한 유용한 실질적인 기술을 개발하게 되리라 확신한다. 이런 기술은 최첨단 동시성 분야의 전문가가 되기 위한 첫걸음이다.
우리가 이 책을 쓸 때 즐거웠던 것처럼 독자 여러분도 이 책을 재미있게 읽기 바란다. - 저자 알렉산더 프로코펙
출판사 서평
★ 이 책에서 다루는 내용 ★
■ JVM의 동시성 모델에 초점을 맞춘 최신 다중 프로세서 시스템상의 동시 프로그래밍
■ 간단한 저수준 동시성 기본 구성요소로 고성능 동시 시스템 구축
■ 퓨처와 프라미스를 사용해 비동기적 동시 계산을 표현하는 방법
■ 데이터-병렬 컬렉션을 사용해 순차적 프로그램을 매끄럽게 병렬로 빨리 수행하는 법
■ Rx 스타일의 이벤트 스트림을 활용해 선언적으로 반응형 이벤트 기반 프로그램 구현
■ 안전하고, 규모 확장성이 있으며, 이해하기 쉬운 메모리 트랜잭션 데이터 모델 설계
■ 여러 기계에서 실행될 수 있는 분산 애플리케이션을 투명하게 작성하는 법
■ 대규모 애플리케이션에서 적절한 분산 추상화 방식을 선택하고, 여러 분산 프레임워크를 통합하는 방법
★ 이 책의 대상 독자 ★
이 책은 스칼라로 동시 프로그램을 작성하고 싶거나, 동시성에 대한 지식을 넓히고 싶은 소프트웨어 개발자에게 꼭 필요한 자습서다.
동시성에 대해 알지 못하는 스칼라 프로그래머를 대상으로 할 뿐 아니라, 이미 동시성에 대해 알고 있지만 좀 더 자세히 알고 싶은 프로그래머도 대상으로 한다. 스칼라에 대해 기본적인 지식이 있다면 도움이 될 것이다. 하지만, 자바 등 다른 언어를 잘 알고 있는 개발자도 쉽게 이 책을 읽을 수 있다.
★ 이 책의 구성 ★
이 책은 동시 프로그래밍의 다양한 주제를 다루는 장들로 이뤄졌다. 스칼라 런타임의 일부인 기본 동시성 API를 다루며, 더 복잡한 동시성 구성요소를 소개하고, 고수준 동시성 추상화에 대해 자세히 소개한다.
1장, ‘소개’에서는 동시 프로그래밍의 필요성을 설명하고, 철학적 배경을 제공한다. 그와 동시에, 이 책의 나머지 부분을 이해하기 위해 필요한 스칼라 언어 기초를 다룬다.
2장, ‘JVM상의 동시성과 자바 메모리 모델’에서는 동시 프로그래밍의 기초를 설명한다. 이 장에서는 스레드(thread)를 사용하는 방법과 공유 메모리에 대한 접근을 보호하는 방법을 배워보고, 자바 메모리 모델을 알아본다.
3장, ‘전통적인 동시 프로그래밍 구성 블록’에서는 스레드 풀(thread pool), 원자적 변수(atomic variable), 동시 컬렉션(concurrent collection) 등의 전통적인 동시성 도구에 대해, 특히 그들이 스칼라 언어의 특징과 어떻게 상호작용하는가에 초점을 맞춰서 제시한다. 이 책은 최신의 고수준 동시 프로그래밍 프레임워크에 중점을 둔다. 따라서 이 장은 전통적인 프로그래밍 기법에 대한 개괄을 제공하지만, 너무 많은 것을 세세히 다루지는 않는다.
4장, ‘퓨처와 프라미스를 사용한 비동기적 프로그래밍’에서는 스칼라용 동시성 프레임워크를 설명하는 첫 번째 장이다. 이 장에서는 퓨처(future)와 프라미스(promise) API를 소개하고, 비동기 프로그램을 작성할 때 어떻게 이들을 제대로 사용하는지 보여준다.
5장, ‘데이터 병렬 컬렉션’에서는 스칼라의 병렬 컬렉션 프레임워크를 설명한다. 컬렉션 연산을 병렬화하는 방법과 언제 병렬화가 가능한지, 어떻게 병렬화의 이점을 평가할 수 있는지를 배워본다.
6장, ‘반응형 확장을 활용한 동시 프로그래밍’에서는 이벤트 기반이나 비동기 프로그래밍에서 반응형 확장(Reactive Extension)을 사용하는 방법을 설명한다. 이벤트 스트림에 대한 연산이 컬렉션 연산과 어떻게 대응하는지와, 한 스레드에서 다른 스레드로 이벤트를 전달하는 방법, 이벤트 스트림을 사용해 반응형 사용자 인터페이스를 설계하는 방법을 알아본다.
7장, ‘소프트웨어 트랜잭션 메모리’에서는 트랜잭션 프로그래밍을 위한 라이브러리인 스칼라 STM(ScalaSTM)을 소개한다. 트랜잭션 프로그래밍의 목표는 안전하고 더 직관적인 공유 메모리 프로그래밍 모델을 제공하는 것이다. 공유 데이터에 대한 접근을 규모 확장성이 있는 메모리 트랜잭션을 사용해 보호함과 동시에 교착상태(deadlock)나 경합 조건(race condition)을 감소시키는 방법을 배워본다.
8장, ‘액터’에서는 액터 프로그래밍 모델(actor programming model)과 아카(Akka) 프레임워크를 보여준다. 여러 기계에서 실행되는 메시지 전달(message passing) 분산 프로그램을 어떻게 투명하게 만들 수 있는지 살펴본다.
9장, ‘동시성 실제 활용’에서는 앞에서 소개한 모든 동시성 라이브러리를 정리한다. 이 장에서는 주어진 문제를 해결하기 위해 적절한 동시성 추상화를 어떻게 선택하는지와 여러 다른 동시성 추상화를 함께 사용해 대규모 동시성 애플리케이션을 설계하는 방법을 알아본다..
각 장을 순서대로 읽을 것을 권장하지만, 반드시 그래야 할 필요는 없다. 2장의 내용에 익숙한 독자는 나머지 내용을 바로 공부할 수 있을 것이다. 앞에서 다뤘던 내용에 깊이 의존하는 유일한 장은 9장이며, 이 책에서 다룬 주제를 실용적으로 정리한다.
★ 옮긴이의 말 ★
내가 처음 접했던 컴퓨터는 금성사의 FC-30으로, 8비트, 4MHz(절대 GHz의 오타가 아니다!) Z-80A CPU를 사용하던 귀여운 녀석이었다. 반면, 지금 내가 이 서문을 작성하는 데 사용 중인 컴퓨터는 인텔 코어 i7이 들어 있는 데스크탑으로, 무려 3.9GHz에 4개의 64비트 코어가 들어 있고, 하이퍼스레딩 기능을 통해 4개의 가상 코어를 더 사용할 수 있는 머신이다. 불과 33년이 흘렀지만, z80과 i7 사이의 성능 차이는 2만 2천배다(MIPS로 단순히 비교하자면 Z80A가 0.6MIPS, i7은 133,740 MIPS이다. 물론 MIPS 같은 단위로 성능을 비교해서는 안 된다). 무려 코어가 4개씩 들어간 이유는, 더 이상 클럭 속도를 늘리는 데 한계에 봉착한 프로세서 생산 업체들이 이제는 코어를 늘려가면서 성능 한계를 극복하려 노력하고 있기 때문이다.
하지만, 여러 코어에서 동시에 프로그램을 실행할 수 있는 CPU가 흔해졌다고 해도, 모든 프로그램이 이를 제대로 활용할 수 있는 것은 아니다. 특히, 원래 처리해야 할 데이터의 양이 아주 방대한 빅데이터 분야나, 계산해야 할 양이 많은 기계학습 분야, 또는 사용자가 GUI 등으로 프로그램에 이벤트를 발생시키고, 프로그램은 이를 비동기적으로 처리하면서, 더 쾌적한 사용자 경험을 제공해야 하는 프로그래밍 분야 등에서는 전통적인 단선적 프로그래밍 기법만으로는 컴퓨터 하드웨어가 제공하는 병렬성을 충분히 살리지 못할 가능성이 많다.
또한 동시 프로그래밍이나 병렬 프로그래밍은 진입하기가 쉽지 않다. 먼저, 동시성을 살려서 병렬 처리가 가능하게 프로그램을 작성할 수 있는 법을 배워야 한다. 하지만 대부분의 프로그래밍 교재나 안내서는 그런 부분에 대해 잘 다루지 않거나, 다루더라도 간단한 스레드 활용법 정도를 소개하는 데 그친다. 이런 책을 통해 병렬 프로그래밍에 입문하게 된 개발자는 곧 비결정성이나, 기존의 단선적인 프로그램 흐름에서는 발생할 수 없는 다양한 문제들과 마주치면서 당황하게 된다. 하지만 당황할 것은 없다. 에드가 다익스트라 같은 위대한 전산학자도 1960년대부터 여러분과 같은 문제에 직면하고, 해결하기 위해 고민했으며, 그 외에 수많은 연구자들이나 개발자들도 비슷한 문제를 접하고 고민해 왔지만, 병렬성과 동시성의 모든 문제를 해결해 줄 수 있는 최후의 해결책은 아직 나온 적이 없기 때문이다. 다만 이런 경우에 여러분의 실수를 줄일 수 있는 좋은 안내서가 있다면 매우 바람직할 것이다.
그런 면에서 자바 프로그래머들은 축복받은 축에 속한다. 브라이언 게츠(Brian Goetz) 등이 집필한 『자바 병렬 프로그래밍』(에이콘출판, 2008)은 자바 동시 프로그래밍의 기초부터 응용까지를 잘 다룬 멋진 책이다. 하지만, 그 책이 나온 지 10여 년이 지났고 액터, 병렬 컬렉션, 소프트웨어 트랜잭션 메모리 등의 도구들도 많이 보급되고 있다. 따라서 10년 전에 유효했던(물론 대부분은 지금도 여전히 유효하다) 여러 기초 지식을 잘 설명하면서, 그간의 변화를 반영해 다양한 고수준 동시성 도구를 아우를 수 있는 개론서가 등장할 때가 됐다고 할 수 있다. 이 책은 바로 그런 'JVM상의 동시 프로그래밍'에 대한 개론서 역할을 충분히 할 수 있는 책이다.
동시성 프로그래밍을 할 때, 자바를 사용해 다양한 추상화를 쉽게 구현하고 표현할 수 있다면 좋을 것이다. 비록 자바 8에 람다, 인터페이스 디폴트 메소드 등이 들어가면서 과거보다 훨씬 표현력이 좋아지긴 했지만, 애석하게도 자바는 주류 언어 중에서는 상당히 제약이 심한 언어 중 하나다. 다양한 동시성 도구를 소개하면서 자바 API를 사용하는 경우, 그보다 더 이해하기 쉽고 깔끔한 언어를 활용하는 것보다 오히려 코드 이해가 어려워질 수도 있다. 그런 면에서, 자바 프로그래머에게 스칼라는 또 하나의 축복이라고 감히 말할 수 있다. 이 책은 스칼라를 사용한 JVM상에서의 동시 프로그래밍에 대해 설명하며, 스칼라 코드로 인해 예제 코드는 간결하고 이해하기 쉬워졌다. 따라서 독자 여러분은 문제 자체의 본질과 그 해결 방법에 좀 더 집중할 수 있다. 더구나, 이 책의 저자인 프로코팩은 스칼라의 본산인 EPFL 스칼라 팀의 일원이며, 스칼라 동시성 라이브러리를 작업해온 핵심 멤버라는 점에서, JVM 동시 프로그래밍 책을 저술하기에 가장 적합한 사람 중 하나라고 말할 수 있다.
스칼라 프로그래머라면 주저 없이 이 책을 읽고, 다양한 동시 프로그래밍 도구를 적재적소에 사용하게 되길 바란다. 자바 프로그래머라면, 이 책을 통해 스칼라를 사용해서 얼마나 간결하고 멋진 코드를 작성해 JVM상에서 실행할 수 있는지 경험하는 한편, 다양한 동시성 도구들을 배우고 익히는 기회도 함께 획득하기 바란다. 그리고 자바나 스칼라 프로그래머가 아닌 독자라면, 각종 동시 프로그래밍 도구의 기본적인 개념과 사용 방법, 주의사항 등을 배우고 익히면서, 프로그래밍 언어를 적절히 선택하는 것이 얼마나 코딩 생활을 쾌적하게 만들어줄 수 있는지를 느껴보기 바란다.