기술자료

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

data-p로 열어가는 새로운 세상 : 구글, 구골과 프로그래밍

기술자료
DBMS별 분류
Etc
작성자
dataonair
작성일
2013-12-27 00:00
조회
3086



data-p로 열어가는 새로운 세상

구글, 구골과 프로그래밍



세계 최대 인터넷 검색엔진 중 하나인 구글(Google)은 수학 용어인 ‘구골(Googol)’에서 유래했다. 10의 100제곱을 의미하는 구골과 구골플렉스는 어떻게 탄생했고 그 크기는 얼마나 큰 것일까 또한 이처럼 어마어마한 크기의 수를 프로그래밍 언어가 과연 지원할 수 있을까 이 글에서는 그간 당연하게 여겨지던 프로그래밍 언어에서 수의 크기란 제약에 대해 고찰해본다.



이미 잘 알려져 있듯 구글이란 이름은 아주 큰 수를 뜻하는 구골에서 유래했다. 어떻게 구골이 구글이 됐는지에 대해서 크게 두 가지 설이 존재하는데 이와 관련된 사실 관계를 따져보면 감춰진 진실에 도달할 수 있을 것이다.



구글 이름의 유래

구글과 얽힌 가설 중 가장 널리 알려진 이야기는 구글의 첫 투자자인 벡톨샤임이 구골을 구글로 잘못 적었다는 것이다. 구글 검색엔진을 개발한 세르게이 브린과 래리 페이지는 기술에 대한 확신이 있었지만 당시 대학생이던 그들에게는 창업자금이 없었다. 이를 구하기 위해 이 둘은 실리콘밸리의 팔토 알토에 있는 지도교수의 친구인 엔젠 투자자 벡톨샤임과 만났다. 당시 바쁜 일이 있던 벡톨샤임은 그들에게 구체적인 사업 설명을 듣는 대신 10만 달러 수표를 줬는데, 이 수표에 구골을 구글(google inc)이라고 잘못 적었고, 이 수표를 사용하기 위해 회사명을 구글로 정했다는 이야기가 있다.
또 다른 설은 검색엔진 도메인을 등록하는 과정에서 구골이 아닌 구글이 사명이 됐다는 것이다. 래리 페이지는 첫 개발한 검색엔진을 BackRub이라고 불렀다. 당시 래리 페이지의 사무실은 스탠포트대학교의 Gates Computer Science Building 건물 302호였고, 그 곳을 샨 앤더슨 등의 다른 대학생들과 함께 사용했다. 당시 래리 페이지와 샨 엔더슨은 BackRub의 새로운 이름을 짓기 위해 토론을 거듭했으며, 샨 엔더슨이 제안한 구골플렉스란 이름이 너무 길다고 생각한 래리 페이지는 구골로 이름을 줄이자고 말했다. 괜찮은 생각이라 여긴 샨 레이지는 구골이란 도메인을 검색했는데 이 과정에서 googol의 스펠링을 google로 잘못 생각했다. 때마침 google 도메인은 등록이 가능했고, 몇 시간 뒤에 래리 페이지는 자신과 동료인 세르게이 브린 이름으로 google. com을 등록했다.
이 두 이야기는 모두 그럴싸하지만 벡톨샤임이 투자한 시기는 1998년이고, 구글 도메인은 1997년 9월 15일 첫 등록됐다. 이로 인해 많은 이들은 후자의 이야기가 더 사실에 가깝다고 보고 있다.


구골

구글의 이름이 유래된 구골은 과연 무엇일까 구골은 10의 100승을 뜻하며, 이를 더 쉽게 표현하면 1을 적고 그 뒤에 0을 100개 적어야 한다.

10,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000

구골이란 이름의 탄생 과정은 이러하다. 1938년 미국 수학자인 에드워드 캐스너가 당시 9살이었던 조카에게 가장 큰 수가 무엇이냐고 물었고, 조카는 ‘googol’이라고 답했다. 그 조카가 왜 구골이라고 답했는지 누구도 알 수 없지만 몇 년 뒤에 에드워드 캐스너는 1940년에 출간된 란 책에 구골을 처음 소개했고 이 이름이 오늘날까지 사용되고 있다. 추후 구골플렉스란 이름도 그에 의해 만들어졌다.

이렇게 큰 수는 우리가 일생생활에서 사용할 일이 없을 것만 같지만 좀더 세상을 넓게 바라보면 우주에 퍼져 있는 원자의 개수나 원자를 구성하는 소립자를 수로 표현하는 데 구골은 유용하게 쓰인다.



구골과 70!

이렇게 큰 수도 우리가 수학시간에 배웠던 팩토리얼과 관련지으면 생각만큼 큰 수는 아니다. 한 계산에 따르면 구골은 70!(팩토리얼) 값 수준이란 점만으로 팩토리얼이 예상보다 더 큰 수를 만드는 개념적인 도구임을 재차 깨닫게 된다. 만일 누가 장난삼아 1000!를 계산한다면 그 크기는 실로 우리의 생각보다 훨씬 엄청날 것이다.
구골이 70!과 크기가 비슷하다는 점은 어떻게 확인할 수 있을까 사람이 계산하기에는 한계가 있기 때문에 결국 컴퓨터 프로그래밍을 이용하는 방법이 유일할 것이다. 컴퓨터가 이 세상에 없다면 어떤 수학자가 몇 개월간 70!의 값을 계산하고 논문이나 책으로 발표했을지도 모른다. 본론으로 돌아와 구골의 값이 70!의 크기와 비슷하다는 것은 다음과 같은 식이 성립함을 의미한다.

69! < 구골 < 70! ①식
70!-구골 < 구골-69! ②식

data-p는 수의 크기에 제한이 없어 이러한 큰 수를 계산하는 데 유용하기 때문에 이를 data-p 언어로 표현하면, 자연수 n을 입력받아 n!을 계산하는 함수를 factorial 함수라고 할 때 이 함수를 통해 ①식을 표현하면 다음과 같다. ②식의 경우 독자들이 스스로 표현해보길 바란다.

10**100 > factorial(69)
10**100 < factorial(70)

data-p 언어로 factorial 함수를 만드는 방법에는 여러 가지가 있다. factorial 함수를 재귀적으로나 순차적 함수로 구성할 수도 있지만 여기서는 이해를 돕기 위해 순차적인 함수로 구현했다(<리스트 1> 참조). data-p 언어와 관련된 자세한 정보는 2012년 11월호의 data-p 강좌를 참고하자.



<리스트 1> 팩토리얼 함수
factorial = func(n, (
sum = 1,
for(i=1, i<=n, i++, sum *= i)
));/* 사용법
factorial(10);
*/



factorial 함수를 활용해 69!와 70!을 계산한 결과는 <리스트 2>와 같다. 이를 통해 구골의 값은 69!보다 크고, 70!보다 작다는 것이 쉽게 증명됐다.



<리스트 2> 69!와 70! 계산
>> g = 10 * 100;
100000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000>> factorial(69);
171122452428141311372468338881272839092270544893520369393648040923257279
754140647424000000000000000>> factorial(70);
119785716699698917960727837216890987364589381425464258575553628646280095
82789845319680000000000000000>> g > factorial(69); // 구골과 69!의 크기 비교
#true>> g < factorial(70); // 구골과 70!의 크기 비교
#true



이진법으로 구골 표현

만일 구골을 2진법으로 표현하면 몇 자리나 차지할까 어떤 이의 계산에 따르면 구골의 크기는 2의 333 승에 가깝다.

10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000(2)

이를 2진수로는 다음과 같이 두 가지 방식으로 표현할 수 있다.
2**333 ①식
1 << 333 ②식

①식에서는 2의 333승을 그대로 표현했다면 ②식은 이진수 1을 좌측으로 333번 이동시킨다. ①과 ②식의 값은 같은데, 이해되지 않는다면 디지털과 관련된 기초 이론을 살펴보길 바란다. <리스트 3>처럼 구골의 값이 2**332보다 크고 2**333보다 작음을 data-p 언어로 확인할 수 있다.

2 ** 333 > 2 ** 100
2 ** 332 < 2 ** 100

<리스트 3> 구골과 2의 333승 값 비교
>> g = 10 ** 100;
1000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000>> t = 2 ** 333;
1749800579826409539498001781694097092282535544714569949140616485127962399
3595007385788105416184430592>> t2 = 2 ** 332;
8749002899132047697490008908470485461412677723572849745703082425639811996
797503692894052708092215296>> t > g; // 2의 333승과 구골의 크기의 비교
#true>> t2 < g; // 2의 332승과 구골의 크기의 비교
#true



구골 계산이 가능한 미래의 CPU

“구골을 2진법으로 표현하면 몇 개의 자리수가 필요할까”란 질문은 “디지털 기기로 표현하면 몇 개의 비트가 필요한가”란 질문과 같다. 그러므로 디지털 기기에 333개의 비트만 있다면 구골을 표현할 수 있다. 이와 같은 맥락에서 CPU가 몇 비트까지 발전하면 구골과 같은 수를 소프트웨어적인 도움 없이 하드웨어 수준에서 계산할 수 있을까
최근 CPU는 32비트와 64비트를 모두 지원하며, 언젠가는 64비트를 넘어 128, 256, 512비트 CPU가 등장할지도 모른다. 그 때가 되면 구골처럼 큰 수도 하드웨어 상에서 즉시 계산할 수 있을 것이다. 물리학 등의 분야에서 수퍼컴퓨터로만 계산이 가능한 것들도 고등학교 수업에서 실습문제로 다루고 지금보다 더 작은 PC에서 이를 계산할지도 모르는 일이다. 예컨대 우주에 퍼진 각 물체들의 이동경로의 수라든지 체스나 바둑에서 돌을 둘 수 있는 경우의 수 등이 그것이다.



구골은 그렇게 큰 수가 아니다

따지고 보면 구골은 그렇게 큰 수는 아니다. 실제 프로그래밍에서 구골의 크기도 부족한 경우는 많다. 바둑에서의 인공지능과 사람의 대결을 예로 들면 인공지능 프로그램은 바둑판의 여러 가지 경우의 수를 모두 계산해야 한다. 바둑판에는 가로로 19줄, 세로로 19줄이 있으므로 총 361곳에 바둑돌을 둘 수 있다.
바둑은 두 사람이 돌 하나하나를 각 자리에 채워나간다. 이를 단순화하기 위해서 자신의 돌로 상대의 돌을 빈틈없이 에워싸서 상대의 돌을 없애 사석이 발생한 경우는 제외하면, 첫 돌은 361곳 어디든 둘 수 있고 두 번째 돌은 첫 돌이 위치한 곳을 제외한 360곳 어디든 둘 수 있다. 이를 경우의 수로 표현하면 다음과 같다

. 361 * 360 * 359 * 358 * 357 * … * 3 * 2 * 1

위 경우의 수는 361!과 같은데 구골보다도 더 크다. 그렇다면 바둑판에서 돌을 놓을 수 있는 경우의 수는 구골보다 얼마나 클까 <리스트 1>에서 만든 factorial 함수를 그대로 사용해 이를 계산하면 결과는 <리스트 4>와 같다.

factorial(361) / (10**100)



<리스트 4> 바둑에서 돌을 놓을 수 있는 경우의 수
>> factorial(361); // 바둑의 경우의 수
14379232588848906548323625114998633547549075386447558761272827652992277955
34389618856841908003141196071413794434890585968383968233304321607713808837
05655787966919248618270978003589902110057945010733305079262777172275041226
80867752813688505752654181204350215062346630264344267363262709276464330255
77722695595343233942204301825548143785112222186834487969871267194205609533
30641393571063519720072147337873382698030853510431742036536737798872175655
13450041291061650506154496265581102824241428406627054585562310156375289289
99248573883166476871652120015362189137337137682618614562954409007743375894
90771443991729993713368072845900003449642033706644085333700128428641265439
44950507739545600000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000>> factorial(361) / (10**100); // 바둑의 경우의 수와 구골 크기 비교
35105548312619400752743225378414632684445984830194235257013739387188178601
91380905412211689460793935721225084069557094649374922444590628925082541106
09511201091111446821950629891576909448383654811360608103668889580749612370
13837287142794203497690872080933142242057202793809246492340598819492993788
51862049793318442241709721253779647912871636198326386645193523423353538899
67386214773104296191582390961604938227614388453202495206388520016777772595
54321389870755982681041250648391364316995674820866832484282983780213108618
14571713581949406424931933631255344573576996295455601960337912616560976305
92703720682934554964277521596435555296977621354111536459228829171487464451
78101825536/244140625



data-p 언어는 사칙연산도 분수로 정확하게 계산한다. 만약 소수점 형태의 수로 알고 싶다면 <리스트 5>처럼 math.decimal이란 함수를 이용하면 된다. 이처럼 구골은 바둑에서의 경우의 수를 표현하기에 턱 없이 부족하다. 쓰일 것 같지 않던 구골처럼 큰 수도 지금 우리들에게 있어 그리 큰 수만은 아닌 것이다.



<리스트 5> 소수점 형태로 <리스트 4> 출력
>> math.decimal(factorial(361) / (10**100));
14379232588848906548323625114998633547549075386447558761272827652992277955
34389618856841908003141196071413794434890585968383968233304321607713808837
05655787966919248618270978003589902110057945010733305079262777172275041226
80867752813688505752654181204350215062346630264344267363262709276464330255
77722695595343233942204301825548143785112222186834487969871267194205609533
30641393571063519720072147337873382698030853510431742036536737798872175655
13450041291061650506154496265581102824241428406627054585562310156375289289
99248573883166476871652120015362189137337137682618614562954409007743375894
90771443991729993713368072845900003449642033706644085333700128428641265439
449.505077395456



구골플렉스

앞서 언급했듯 에드워드 캐스너는 구골뿐 아니라 구골플렉스란 수의 이름도 만들었다. 구골플렉스는 원래 1을 쓰고 그 뒤에 0을 지칠 때까지 써야 하는 수를 의미하지만 사람들마다 다른 값이 되기 때문에 후에 구골플렉스의 크기는 1 뒤에 0의 개수를 구골 크기만큼 붙인 수로 수정됐다. 말하자면 다음 수식이 바로 구골플렉스다.

googolplex = 10googol
위의 구골플렉스를 data-p 언어로 표현하면 다음과 같다.

googolplex = 10**(10**100)

그러나 이 식을 실제로 계산하지는 말자. 왜냐하면 data-p 언어를 포함해 어떤 프로그래밍 언어도 이 크기를 계산할 수 없기 때문이다. 만약 위 식을 계산하려고 시도해도 data-p 인터프리터는 끝없이 계산만 하고 답을 내지 못할 것이다. 그렇다면 구골플렉스는 얼마나 큰 수일까 구골플렉스의 크기는 우주에서 가장 작은 크기 단위인 플랑크 길이(Planck Length)보다 더 많은 자릿수를 갖고 있다. 1플랑크 길이는 1.6162×10-35m이며, 이는 어떠한 측정 장비로도 측정할 수 없을 정도로 작은 크기로 알려져 있으며, 우주의 크기는 현재로서 3×1080m3로 여겨지고 있다. 그렇다면 이 우주에 몇 개의 플랑크 부피가 존재하는지를 계산해보자.

3×1080 / (1.6162×10-35)3

<리스트 6>은 위 식을 data-p 언어로 표현한 것으로, 계산해보면 약 7.1×10184개의 플랑크 부피가 존재한다. 그러나 이 수는 구골플렉스보다도 훨씬 적은 수다.

3*(10**80) / (1.6162*10**-35)**3



<리스트 6> 우주에서 가장 큰 것을 가장 작은 것으로 나눈 값
>> num = 3*(10**80) / (1.6162*10**-35)**3;
37500000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000/527709995441>> math.decimal(num);
71061758018552907480591054185091463170741468979951786169676892891089717250
91057767884126440248872375157963954340750919708710168372798805426445877355
3026375524904295954290586222756405202.75615644836239079814>> math.float(num);
7.10617580186e+184f



프로그래밍 언어가 다룰 수 있는 수의 범위

과거 윈도우 운영체제가 나오기 이전에 DOS란 운영체제가 사용됐다. 당시 대부분의 CPU는 16비트였고, C 언어에서 표현 가능한 최대 크기는 2의 16승인 65,536이었다. 메모리의 주소도 이 범위 내에서 다 해결됐고, 데이터를 읽고 쓸 때에도 16비트만 사용해 전혀 문제가 없었다. 시간이 흘러 32비트 CPU가 등장하면서 컴퓨터로 232(2의 32승)을 표현할 수 있게 됐다. 사실 대부분의 프로그래밍 언어에서 이 정도의 크기면 충분하다고 생각했고 64비트 CPU가 등장한 지금도 대부분의 프로그램은 32비트로 개발되고 있다.
그러나 앞서 소개한 바둑을 비롯해 구골, 구골플렉스의 경우만 봐도 32비트나 64비트 기반의 전통적인 프로그래밍 언어로 이를 계산한다는 것은 쉽지 않다. 프로그래밍 언어가 우리의 사고를 바로 표현하지 못한다면 이는 우리에게 제약사항이 될 뿐이다. 이런 이유로 프로그래밍 언어에 존재하는 수의 제약을 없애는 방향으로 프로그래밍 언어는 발전해야 할 것이다.