이 글은 구글 직원의 'Databases are hammers; MapReduce is a screwdriver.'를 번역한 글입니다.
많은 사람들이 맵리듀스에 관한 기사를 많이 보내왔다. 요새 맵리듀스 열풍이 불고 있는데다 나를 고용한 구글이 많이 쓰는지라 이걸 쓸까말까 고민을 했다. 하지만 이 기사는 진짜 짜증나는데다 그에 대한 반응이 필요하다. 그래서 확실히 하려고 한다. 나는 이걸 내가 구글 직원으로서 쓰는 글이 아니다. (사실 나는 직장에서 맵리듀스를 써본 적도 없다!) 이는 내가 내 시간에 해본 경험으로 말하는 것이고 순전히 나의 의견일 뿐이다. 만약 이 글이 멍청하다고 생각한다면 그건 내 잘못이지 구글의 잘못이 아니다. 좋은 글이라고 생각한다면 그건 내가 잘난 거지 구글이 잘난 게 아니다. 구글이 쓰라고 해서 쓰는 게 아니고 구글한테 허락을 구한 적도 없다. 그냥 누구를 위해 쓰는 게 아니라 나를 위해 쓰는 이 공돌이 블로그 주인장의 의견일 뿐이다.
맵리듀스에 관심이 가는 이유는 이게 내 박사 학위 작업과 연관이 있기 때문이다. 학부생 때, 불특정 어플리케이션에서 정형 데이터에 병행 처리를 적용하는 방법을 연구한 적이 있다. 맵리듀스가 지금 하는 것이랑 좀 비슷하다. 그리고 그때 내가 처리한 해결책은 위계적인 흩뿌리기/모으기 연산이었다. 그리고 그건 맵리듀스가 하는 거랑 진짜 비슷하다. 큰 차이점은 맵리듀스가 내 것보다 좋다는 것 뿐이다. 맵리듀스를 설계한 이들은 내가 알아채지 못한 무언가를 더 좋게 해서 더 깨끗하고 작성하기 쉽게 만들었다. 이 글에선 맵리듀스에 대해서 중점적으로 말하지 않겠다.
처음부터 시작해보자. 맵리듀스가 무엇인가? 맵리듀스는 무엇을 하는가?
직장에서 뭔가 엄청 오래 걸리는 작업을 컴퓨터로 돌릴 때 우리는 모두 기다리기 싫어한다. 하지만 그렇다고 십억이나 하는 슈퍼컴퓨터를 사기도 싫다. 이때 우리는 어떻게 이 작업을 빠르게 할 수 있을까? 한 가지 방법은 싼 컴퓨터를 여러 개 사서 한 꺼번에 돌리는 것이다. 다른 방법으로는 직장에 있는 많은 컴퓨터로 시선을 돌리는 것이다. 사무실에는 보통 컴퓨터가 직원마다 하나 씩 있는데 그걸로 하는 일은 별로 없다. 그러니 이를 이용하면 어떨까? 당신의 컴퓨터가 일을 많이 안 한다면 동료에게 당신이 사용하지 않는 부분을 좀 빌려줄 수 있고, 당신이 필요할 때면 그의 것을 빌릴 수 있다. 이렇게 하면 뭔가 큰 걸 돌릴 때 여러 기계를 쉽게 돌릴 수 있다.
이 접근법의 문제점은 대다수의 프로그램이 여러 기계에서 돌아가도록 짜여있지 않다는 점이다. 프로그램들은 한 컴퓨터에서 돌아가도록 짜여졌다. 일을 많은 컴퓨터에게 나눠주는 것은 어렵다.
맵리듀스는 여러 컴퓨터에게 일을 쉽게 나눠줄 수 있는 프로그램을 정해진 스타일로 프로그래밍할 수 있게 해주는 라이브러리이다. 일을 맵과 리듀스의 두 부분으로 나누는 것이 기본 아이디어이다. 맵은 문제를 받아서 부분으로 나눠서, 각 조각들이 동시에 실행될 수 있도록 이를 서로 다른 컴퓨터들에게 전달한다. 리듀스는 부분들의 결과를 받아서 다시 결합해 하나의 답을 도출한다.
맵리듀스가 일을 하는 방식의 핵심은 입력을 레코드의 목록의 형태로 받는 것이다. 맵은 레코드를 서로 다른 컴퓨터들에게 나눈다. 맵 연산의 결과는 키/값 쌍의 리스트이다. 리듀스는 같은 키를 가진 값들의 각 집합을 하나의 값으로 합친다. 즉 맵은 데이터를 받아서 키/값 쌍을 생성하고 리듀스는 이를 합친다. 이 과정에서 키/값 쌍 대신에 하나의 결과를 받아볼 수 있는 것이다. 일이 100조각으로 나뉠지 2조각으로 나뉠지는 알 수가 없고 결과는 어찌 됐든 하나의 맵에서 나온 것처럼 보이게 될 것이다. (내 박사 과정에서 만든 거랑 맵리듀스가 다른 점은 결과값을 키/밸류의 매핑으로 처리해서 깨끗하고 일관된 리듀스 과정을 거친다는 점이다. 나는 이를 흩뿌리기/모으기 패턴으로 해결하려고 했는데 내 방법은 맵리듀스에 비하면 엄청 별로였다.)
맵리듀스의 미학은 프로그래밍하기가 쉽다는 것이다. 맵리듀스 프로그램은 병렬 프로그래밍으로 할 수 있는 최고의 심플함을 보여준다.
글의 주제로 다시 돌아가보자. 사람들은 맵리듀스가 관계형 데이터베이스에 기반하지 않는다고 말한다.
내가 관계형 데이터베이스를 처음 배우고자 할 때 당시 내 상사가 데이터베이스 쪽 일을 하는 사람들에 관한 얘기를 해줬다. 그리고 내가 실제로 겪어보니 완전 맞는 말이었다. 무슨 이야기냐면, 관계형 DB 쪽 사람들은 세상에서 가장 아름답고 멋지고 완벽한 망치를 가졌다는 것이다. 관계형 DB는 엄청 무겁지도 가볍지도 않고 매번 못을 정확히 두드릴 수 있도록 완벽한 균형을 이룬다. 손잡이를 손 모양에 딱 맞게 커스터마이징 할 수도 있어서 물집 안 잡히고 맨날 쓸 수 있다. 또한 아릅답게 장식되어 있기도 하다. 보석으로 덮혀있고 도금도 되어 있는데 망치질하는데 방해가 안 되는 곳에만 딱 되어 있다. 진짜 대단한 도구다! 게다가 그 망치로 뭔가 만들 때면 더 대단해진다. 사실, 그쪽 사람들은 이 망치를 엄청나게 좋아해서 그 망치만 있으면 된다고 생각한다. 이들에게 나사를 쥐어주면 못인 것마냥 냅다 망치로 박아버릴 것이다. 그것 보고 이건 나사지 못이 아니라고 말하면 그들은 "알아. 근데 내가 이 훌륭한 망치를 두고 쓰레기같은 드라이버를 쓸 거란 생각은 버려!"라고 할 것이다.
이게 이 글의 주제이다. 그들에겐 관계형 데이터베이스가 있다. RDB는 정말 눈부신 것이다. RDB는 대단한 도구여서 대단한 소프트웨어를 만드는 데 쓰일 수 있다. 나는 RDB로 많은 일들을 해왔다. 없이도 해봤는데, 이들은 그렇게 자랑스럽다고 말할 순 없다. 나는 RDB를 깎아 내리고 싶진 않다. RDB는 참으로 대단하다. 하지만 모든 게 관계형 데이터베이스인 것은 아니고 모든 것이 이에 자연스레 어울리는 것이 아니다. 이 점을 무시한 채, 맵리듀스를 향한 비판은 "근데 이건 관계형 데이터베이스가 할 만한 일이 아니잖아!"로 일축된다. RDB는 딱히 병렬적이지가 않다. 싼 컴퓨터 1000대한테 작업을 효율적으로 나눠줄 수 있는 RDB를 몇 개나 알고 있는가? RDB는 표가 아닌 데이터를 잘 다루지 못한다. RDB는 재귀적 자료구조에선 낮은 성능을 보이기로 악명이 높다. 맵리듀스는 관계형 데이터베이스를 대체하려고 만들어진 것이 아니다. 많은 컴퓨터에서 병렬적으로 돌리는 프로그램을 쉽게 짜기 위한 것이다. 그게 맵리듀스가 의도한 것이다.
정확히 말하자면, DB 사람들이 말하는 맵리듀스는
1. 큰 스케일의 데이터에 집중하는 애플리케이션을 위한 프로그래밍 패러다임에서 크게 역행한다.
2. 인덱싱 대신 브루트 포스를 이용하는, 일부만 최적화된 구현이다.
3. 전혀 새롭지 않다. -- 약 25년 전에 개발된 잘 알려진 기술을 구현한 특정 방식에 불과하다.
4. 현재 DBMS에 있는 많은 기능들을 포함하지 않는다.
5. DBMS가 의존하고 있는 모든 도구들과 호환되지 않는다.
1번은 개소리이다. 맵리듀스는 큰 스케일의 데이터에 집중하는 몇몇 애플리케이션의 개발에 좋은 방법이다. 관계형으로 표현된 데이터를 많이 연산할 일이 있고 그게 엄청 큰 컴퓨터 한 대에서 돌릴 수게 돼있고, 실제로 그 컴퓨터에 접근할 수 있다면, 말할 것도 없이 RDB를 써야 한다. 그리고 적절한 인덱싱과 테이블 레이아웃을 쓰면 복잡해 보이는 연산들도 하나의 컴퓨터에서 쓰기 괜찮아지기 때문에 불가능해보이는 것들도 쉽게 만들 수 있다. 하지만 모든 연산이 다 그렇지는 않다. 대부분의 연산이 그렇지 않다. 맵리듀스는 관계형 데이터베이스를 대체하기 위한 것은 아니다.
예를 하나 들자면 내가 프랙탈에 대해 쓰고 있을 때 한 독자가 BuddahBrot에 매료되어서, 프랙탈 이미지를 생성하는 NebulaBrot을 만들려고 한 적이 있다. 기본적인 아이디어는 만델브로 집합의 경계에 있는 점들 집합을 가져다가 이들의 경로를 만델브로 반복을 거치면서 추적하는 것이다. 이 경로들을 점들이 거쳐가면 거쳐갈 수록 밝아진다. 결과로 아주 멋진 이미지를 얻을 수 있다. 문제는 확대할 수 없다는 것이었다. 경로가 불규칙해서 어떤 시작점이 특정 부분을 지나는 경로의 시작인지 알아내는 방법이 없었다. 그래서 그 똑똑한 독자가 한 일은 큰 NebulaBrot 을 만드는 것이다. 작은 곳에서 시작해서 확대하는 대신 크게 시작해서 줄이는 것이다. 이렇게 하면 작은 부분을 큰 해상도로 볼 수 있다.
NebulaBrot 이 구현된 방식이 바로 맵리듀스와 같다. 독자는 수백만 개의 점들을 지나는 경로를 추적해야 했다. 이는 시간이 좀 걸린다. 그래서 그가 한 일은 시작점들을 부분집합으로 나눠서 그들을 맵으로 만든 것이다. 각각의 맵 인스턴스는 점들의 경로를 그리는 연산을 수행했다. 맵의 결과는 점들과 경로가 점들을 지나는 횟수의 쌍이었다. 점들이 키고, 지나가는 횟수가 값이다. 리듀스는 점과 횟수 쌍을 받아서 각 점들을 지나는 교차로를 그린다. 그리고 그 결과가 이미지로 번역이 된다. 엄청 빠르다! 위대한 NebulaBrot, 아주 빠르다.
우리는 이걸 관계형 데이터베이스에서 할 수 없다. 이건 관계형 어플리케이션이 아니다. 이는 행 데이터에서 시작하지가 않는다. 맵리듀스는 입력 데이터의 집합을 행이라고 부르긴 하는데 이건 비유일 뿐이다. 여기서 데이터는 리스트로 나타내진 데이터가 아니다. NebulaBrot에서 데이타는 실제로 행이 아니라 점들로 이루어져 있다. 그리고 관계형 도구는 여기서 할 수 있는 일이 없다. 작은 컴퓨터 한 대로 그 연산을 추적할 수 있게 하는 섬세하고 우아한 테이블 레이아웃과 인덱싱 방법이란 없다. 또한 관계형 도구는 그걸 병렬적으로 실행하는데 아무런 도움을 주지 못한다.
2번은 맵리듀스가 인덱싱을 사용하지 않아서 원시적이고 일부만 최적화된 데에 그친다고 이야기 한다. 기본적으로 이에 대한 반응은 이전 것과 같다. 인덱싱은 좋은 것 맞다. 근데 그건 데이터가 일렬로 되어 있고 중점으로 쓸만한 인덱스가 있을 때의 이야기이다. 데이터가 기본적으로 관계형이 아니라면 필요한 건 NebulaBrot에서처럼 엄청난 양의 부동소수점 곱셈과 같은 연산인데 그럼 인덱스는 사실 별 도움이 안 된다. 맵리듀스가 해결하려고 하는 문제는 엄청난 양의 연산을 합리적인 시간 안에 할 수 있는 프로그램을 쉽게 작성하는 것이다. 핵심 작업이 연산인 경우에 인덱스는 별 도움이 되지 않는다.
3번, "새롭지 않다" 아니 잠깐 뭔 소리야! 새롭다고 말한 적이 없구만. 새로워야 하는 것도 아니고. 사실 맵리듀스의 첫 발표자료는 함수형 프로그래밍의 맵과 리듀스에서 영감을 얻었다고 말한다! 맵리듀스는 기본적으로 데이터 병렬 컴퓨팅의 한 형태이다. 그 말인 즉슨 병렬 컴퓨팅 모델의 잘 알려진, 이해하기 쉬운, 쓰기 쉽고 확장 가능한 구현이란 말이다. 이게 어떻게 문제가 될 수 있지?
4번. "RDBMS의 기능이 없다" 1번을 다르게 말한 거 아닌가? 그냥 "관계형이 아니잖아, 그러니 좋은 게 아냐"를 또다른 방식으로 말한 것이다. 다시 한 번 말하는데, 의도가 중요하다. 맵리듀스는 데이터베이스 어플리케이션이 아니다. 관계형 데이터베이스 문제가 있다면 관계형 데이터베이스를 쓰면 된다. 수십, 수백, 수천 개의 컴퓨터들한테 나눠줄 엄청 큰 연산 문제가 있다면 맵리듀스를 쓰면 된다. 그 대단한 DBMS 툴? 대량 병렬 클러스터/클라우드 컴퓨팅하려고 만들어진 게 아니다. 실제로 DBMS 툴들은 거대한 클러스터 환경에서는 작동하지 않는다.
5번, "DB 개발자가 의존하고 있는 툴들과 호환되지 않는다." 내가 왜 망치 이야기를 꺼냈는지 보이지 않는가? 이것도 또 아까 그 낡아빠진 비판이랑 똑같은 말이다. 맵리듀스는 관계형 데이터베이스가 아니니 좋지가 않다. 아니, 데이터베이스 지향 툴과 프로세스들은 맵리듀스 프로그래밍을 위해서 작동하지 않는다. 사실 좋은 DB 설계는 엄청 구린 맵리듀스 설계를 만들곤 할 것이다. 둘은 같은 일을 하려는 게 아니니까.
그래서 결론적으로, 데이터베이스 사람들이 맵리듀스를 비판하는 말 중 들을 가치있는 말이 있을까? 솔직히 그렇게 생각 안 한다. 그들은 맵리듀스가 무엇을 위해, 그리고 왜 그런 식으로 설계되었는지를 이해하지 못하는 것 같다. 맵리듀스가 "테이블"과 "행"이란 단어를 사용한다는 사실 때문에 관계형 DB랑 똑같은 줄 알고 그게 RDBMS에서 할만한 일들을 하기 위해 만들어진 줄 아는 것 같다. 용어에서 나타나는 외관적으로 비슷한 부분을 빼면 둘 사이엔 연결점이 거의 없다. 맵리듀스는 연산 작업들을 위한 좋은 도구다. RDBMS를 까내리는 게 아니다. 관계형 데이터베이스도 또한 큰 연산 작업에 좋은 툴이다. 관계형 데이터베이스의 접근법이 모든 작업에 있어서 최적의 솔루션이 아니라는 사실은 맵리듀스의 탓이 아니다. 맵리듀스가 RDBMS와 다른 목적을 가졌는데도 비슷한 용어를 사용한다는 것은 맵리듀스가 틀렸다는 이야기가 아니다. 맵리듀스는 관계형 데이터베이스의 새로운 버전이 아니다. 맵리듀스는 완전히 다른 것이다.
세상에서 가장 좋은 망치를 가졌다고 해서 세상 모든 게 못이 되지 않는다. 나사가 있으면 싸더라도 스크류 드라이버를 쓰는 게 낫다. 그리고 맵리듀스는 싸고 낡고 녹슨 스크류드라이버보다 훨씬 낫다.