이 책을 쓰는 시점에도 일반적인 데스크탑 시스템에서조차 멀티코어 프로세서가 비싸지 않은 가격으로 대중화되어 가고 있다. 우연찮게 수많은 개발팀이 진행하는 프로젝트에서 스레드와 관련된 버그가 자꾸만 늘어나고 있다는 사실을 쉽게 알 수 있다. 넷빈즈(NetBeans) 개발 사이트에 최근에 올라온 글을 보면, 단 하나의 클래스를 놓고 스레드 관련 문제점을 수정하기 위해 14번이나 코드를 수정했다는 사실을 핵심 유지보수 담당자가 알아차린 사례도 있다. TheServerSide의 편집장을 지냈던 디온 앨메어는 (결국 스레드 관련 문제라고 결론이 나왔던 고통스러운 디버깅 작업을 끝낸 이후에) 대부분의 자바 프로그램이 "어쩌다보니 실수로 동작하는" 것일 뿐이며 스레드 관련 버그가 굉장히 자주 발생한다는 내용의 블로그 포스트를 올린 적도 있다.
스레드 관련 오류는 예측 가능한 상태로 스스로를 드러내는 법이 거의 없기 때문에 스레드를 사용하는 프로그램을 개발하고 테스트하고 디버그하는 일은 실제로 엄청나게 어려운 일이 될 수 있다. 게다가 문제점은 항상 최악의 시점, 즉 실제 사용 환경에서 부하가 많이 걸릴 때 주로 나타난다.
자바로 병렬 프로그램을 작성할 때 넘어야 할 가장 큰 산중의 하나는 플랫폼에서 제공하는 병렬 프로그래밍 기법과 개발자가 자신의 프로그램에서 병렬 프로그래밍 기법을 어떻게 사용하려 하는지 간에 큰 차이가 있다는 점이다. 자바 언어에서는 동기화나 조건부 대기와 같은 저수준의 도구(mechanism)를 제공하지만, 이런 도구를 사용해 애플리케이션 수준의 규칙이나 정책(policy)을 일관적으로 구현할 수 있어야 한다. 컴파일 잘 되고 실행도 잘 된다고 생각되는 프로그램은 쉽게 작성할 수 있겠지만, 이런 정책이 없다면 오류가 금새 나타나고야 만다. 병렬 프로그래밍에 대한 다른 훌륭한 책이 많지만 대부분 설계 수준의 정책이나 패턴에 대해서 다루기 보다는 저수준의 API에 집중하고 있어 이와 같은 정책의 중요성에 대처하는 면이 부족했다고 생각된다.
자바5.0은 고수준의 컴포넌트와 저수준의 도구를 모두 제공하기 때문에 초보자나 전문가 모두가 병렬 프로그램을 쉽게 작성할 수 있게 되었다는 점에서 큰 발전을 이뤘다고 볼 수 있다. 이런 기능을 실제로 구현하는데 참여했던 JCP 전문가 그룹에서 이 책을 쓰는데 많이 참여했다. 추가된 기능과 동작하는 구조를 설명하는 것뿐만 아니라 그 기반이 되는 디자인 패턴과 함께 플랫폼 라이브러리에 추가되는데 중요한 역할을 했던 예상 활용 시나리오도 함께 소개한다.
이 책을 읽는 독자는 여러 가지 설계상의 규칙을 이해하고, 또한 자바 클래스나 애플리케이션이 올바르게 높은 성능으로 동작하도록 작성하는 과정이 더 쉽고 재미있는 일이 되도록 만들고자 하는 목표가 있다.
『자바 병렬 프로그래밍』을 즐겁게 읽고 유익하게 활용하길 바란다.
--- 저자 서문, 브라이언 괴츠(Brian Goetz)
학교를 졸업하고 처음 회사에 취직한 이후에 담당했던 개발 업무 가운데 상당 부분은 자바로 서버 프로그램을 작성하는 일이었습니다. 수십에서 수백 대에 이르는 클라이언트를 대상으로 24시간 동작하는 서버를 작성하는 업무는 꽤나 재미있었습니다. 몇 날 며칠을 고생해서 만든 서버 프로그램이 어딘가 누군가의 서버에 설치되어 24시간 동작하면서 제 할 일을 하고 있는 모습을 보면 건방지게도 자식이 제 할 일을 잘 할 때 부모가 받았을 느낌을 느낄 수 있었다고도 생각합니다.
하지만 어려운 병렬 처리 이론이 아닌 멀티스레드를 사용해 프로그램하는 실습 위주의 교육을 받은 적이 없는지라, 단순하게 멀티스레드로만 동작하는 '자식같은' 프로그램이 알 수 없는 오류를 뿌리면서 곳곳에서 뻗어버리는 모습을 보면 참 안타까웠습니다 (오류라도 뿌리고 죽으면 그나마 다행입니다). 예전 버전의 자바는 운영체제마다 스레드의 동작 모습이 많이 달라서 어려운 점도 많았습니다. 운영체제마다 다른 스케줄링 문제를 해결하기 위해 전반적인 성능을 떨어뜨리면서 쓸모없는 I/O 구문을 추가하는 작업도 서슴치 않았습니다. 이후 스레드 풀을 적용해 서버의 안정성을 크게 높여주고, 스핀락(spin-lock)을 사용했던 부분에 wait-notify 구조를 적용해 CPU 부하를 크게 줄이기도 했습니다. 그러던 도중에 자바5.0이 발표되고, 병렬 프로그래밍을 위한 도구가 엄청나게 많이 제공되기 시작했습니다. 여기저기 찾아보며 만들고 안정화하느라 애를 먹었던 스레드 풀을 메소드 호출 한방으로 만들 수 있었으며, 훨씬 다양한 병렬 프로그래밍 기능을 더 안정적으로 제공받을 수 있게 되었죠.
이제 어느 프로그램에나 멀티스레드 구조를 활용하는 일은 거의 기본이 되어갑니다. 제가 요즘 맡은 개발 업무에서도 완전히 서로 다른 분야의 동떨어진 목표를 향해 개발하지만, 어느 곳 하나 스레드를 활용하지 않는 프로젝트가 없습니다. 서버에서는 한정된 컴퓨터 자원을 최대한 활용해 가장 효율적으로 서비스를 제공하고자 하고, 클라이언트 PC에서는 동적인 인터페이스와 함께 많은 정보를 실시간으로 얻고자 하죠. 단순히 언어와 관련된 문제는 아닙니다. 자바이건 C#이건 PHP이건 간에 항상 멀티스레드 환경을 생각해야 합니다. 직접 스레드를 만들지 않더라도 외부의 어디선가 반드시 스레드를 사용하는 부분이 있게 마련입니다.
이런 시점에 스레드를 활용한 병렬 처리에 대한 실제적인 예제와 패턴을 적용한 사용 예를 소개하는 너무나 반가운 책이 바로 『(멀티코어를 100% 활용하는) 자바 병렬 프로그래밍』입니다.
병렬 프로그램을 작성할 때 보통은 자바5.0부터 추가된 java.util.concurrent 패키지에 대한 여러 문서를 보면서 대충 이해하고 사용하곤 하지만, 『자바 병렬 프로그래밍』은 이런 기능을 충분히 이해한 상태에서 활용하도록 도와주고 있습니다. 아주 간단한 클래스를 담당해 개발하고 있다고 해도, 해당 클래스가 큰 규모의 프로그램에서 기본적인 부분으로 널리 사용된다면 이 책에서 소개하는 기법을 적절히 적용해 전체 프로그램의 안전성을 확보하면서 성능을 크게 높일 수 있습니다. 그리고 병렬 프로그래밍에 대한 기초를 다지고 나면, 기존에 잊을만 하면 한 번씩 오류를 뱉어내면서 문제가 생기던 프로그램에 어떤 원인이 있을 수 있는지 쉽게 추적할 수도 있습니다. 『자바 병렬 프로그래밍』이 전문적인 이론서는 아니지만, 이론을 소홀하게 다루지도 않습니다. 또한 자바 언어를 기반으로 한다는 가정하에 쓰여진 책입니다만, 일반적인 병렬 처리 이론을 적용한 부분이 많으며 하드웨어나 시스템 구조와 관련된 부분도 적지 않기 때문에 다른 언어에도 쉽게 적용할 수 있는 내용이 많습니다.
한발 더 나아가 미래를 내다보는 개발자는 이미 단일 컴퓨터 내부에서의 병렬 처리를 넘어 여러 대의 컴퓨터에서 병렬로 동작하는 플랫폼을 찾고 있고, 이와 같은 분산 병렬 처리 플랫폼이 한창 인기를 얻는 요즘입니다. 이런 대규모의 병렬 처리 플랫폼도 중요하긴 하지만, 그 안에서는 항상 단일 프로세스 내부에서 동작하는 여러 스레드가 안정적으로 실행되도록 하는 병렬 처리 기법이 적용되어 있음을 잊어서는 안될 것입니다.
재미있겠다고 생각은 했지만 내용이 어렵겠다고 지레 겁을 먹고 사양했던 번역 작업인데, 결국 이제야 끝마치게 되었습니다. 나름 서버 프로그래밍을 통해 경험을 많이 쌓았다고 생각했지만 책을 꼼꼼히 읽는 과정에서 배운 점이 더 많았습니다. 여러분 모두 이 책을 통해 자신있게 스레드를 널리 활용하고 결과물의 성능과 안전성을 높일 수 있게 되길 바랍니다.
참고로, 이 책에서 '병렬'이라는 단어로 표시한 내용의 대부분은 'concurrent'라는 영어 단어를 의미합니다. concurrent의 뜻은 특히 컴퓨터 용어로 쓰일 때 '동시에 실행되는 코드의 흐름'이라고 풀어 쓸 수 있겠습니다. 원래 '병렬'은 일반적으로 'parallel'이라는 단어를 번역할 때 많이 사용합니다. 하지만 parallel과 concurrent는 약간의 뉘앙스 차이가 있음에도 불구하고 비슷한 의미로 볼 수 있기 때문에 '병렬'이라는 단어를 사용했다는 점을 알립니다.
마지막으로 이 책을 번역할 수 있게 물심 양면으로 도움을 아끼지 않았던 아내 선영과 아들 강헌에게 고맙다는 인사를 전합니다. 가족은 항상 저를 든든하게 만드는 능력이 있습니다.
<b>--- 역자 서문</b>