Skip to content
Jacob's second brain 탐색
어느 개발자의 인문학 · 12 / 16화

bug - 완벽한 프로그램은 없다

5 min read

프로그램에 생긴 오류를 ‘버그(bug)‘라고 부릅니다. 영어로 벌레라는 뜻이지요. 딱딱한 기계의 오류에 하필 꿈틀거리는 벌레의 이름이 붙었다는 게, 생각해보면 조금 재밌습니다.

여기엔 유명한 일화도 하나 있습니다. 1947년, 하버드 대학의 커다란 컴퓨터가 갑자기 말을 듣지 않아 기술자들이 부품을 열어보니, 나방 한 마리가 전기 접점 사이에 끼어 죽어 있었습니다. 그들은 그 나방을 떼어내 작업 일지에 테이프로 붙여두고, 그 옆에 이렇게 적었습니다. “버그가 발견된 최초의 실제 사례.” 오류를 벌레라 부르던 사람들 앞에 정말로 벌레가 나타났으니, 말 그대로 진짜 버그라며 남긴 웃픈 농담이라고 볼 수 있습니다.

이름은 벌레지만, 정작 버그는 이렇게 밖에서 기어든 벌레인 경우가 오히려 드뭅니다. 대개 버그는 우리가 만든 것 안에서 생깁니다.

버그는 어디로부터 오는가

그렇다면 버그는 어디서 올까요. 가장 흔한 것은 역시 사람입니다. 앞서 보았듯 컴퓨터는 시킨 그대로만 따르는 눈치없는 기계입니다. 그래서 사람이 한 군데를 잘못 시키면, 기계는 그 잘못을 의심 없이 충실하게 실행해버립니다. 무언가를 빠뜨리기도 하고, 잘못된 가정을 세우기도 합니다. 때로는 미처 생각하지 못한 상황을 만나기도 하고요. 소프트웨어의 버그는 대개 이렇게 사람이 자기도 모르게 심어둔 실수에서 비롯됩니다.

그러나 모든 버그가 사람의 실수인 것은 아닙니다. 멀쩡하던 부품이 닳거나 망가지기도 합니다. 남이 만들어 가져다 쓴 부품에 결함이 숨어 있는 수도 있고요. 어제까지 잘 돌던 프로그램이, 오늘 갑자기 말을 안 듣기도 합니다. 너무 오래된 이야기지만, 그래도 이를 이해할 수 있는 가장 유명한 예는 이른바 ‘밀레니엄 버그’인 것 같습니다. 옛 컴퓨터들은 저장 공간을 한 톨이라도 아끼려고 연도를 끝 두 자리로만 적었습니다. 1998년을 그냥 ‘98’로 적는 식이었지요. 멀쩡한 방식이었습니다. 적어도 1999년에서 2000년으로 넘어가기 전까지는요. 막상 그 순간이 닥치자, 수많은 프로그램이 ‘00’을 2000년이 아니라 1900년으로 읽어버릴 판이었습니다. 누가 실수를 한 것도 아니었습니다. 그 코드를 짤 때만 해도 옳았던 전제가, 세월이 흐르며 더는 맞지 않게 된 것이지요. 이 문제는 세상이 달라진 탓에 생긴 것입니다. 만든 사람에게 잘못이 있다면, 설마 2000년이라는 순간이 온다는 예상을 못한 것입니다.

앞서 본 1947년의 나방도 그렇습니다. 이건 사람이 저지른 실수가 아니었지요. 정말로 바깥에서 벌레 한 마리가 기어 들어와 기계를 멈춰 세운, 드문 경우였으니까요.

그러니 버그를 하나로 묶어주는 건 ‘누구의 잘못이냐’가 아닙니다. 원인이 사람이든 부품이든 우연한 침입자든, 버그가 가리키는 것은 늘 한 가지입니다. 공들여 만든 무언가가 어느 부분에선가 뜻대로 움직이지 않게 되는 일. 복잡한 것을 만들어 세상에 내놓는 한, 그런 일은 늘 어디선가 나옵니다. 누군가 복잡한 프로그램을 만들었는데 영원히, 어떠한 상황에서든 단 한 개의 버그도 없을거라고 단언한다면, 그것은 분명 거짓말일 것입니다.

참을 수 없는 코드의 복잡함

밀레니엄 버그가 일러주는 것은, 버그가 단지 부주의의 문제만은 아니라는 사실입니다. 그 뿌리에는 더 근본적인 무언가가 있습니다. 소프트웨어가 감당해야 하는 복잡함이, 사람이 머릿속에 다 담을 수 있는 크기를 한참 넘어선다는 것입니다.

우리가 무심코 쓰는 프로그램들이 실은 얼마나 거대한지, 우리는 잘 실감하지 못합니다. 스마트폰의 평범한 앱 하나가 수만 줄의 코드로 이루어져 있고, 자동차나 여객기를 움직이는 소프트웨어는 수천만 줄에 이릅니다. 그리고 그 코드들은 따로 노는 것이 아니라, 서로가 서로를 부르고 영향을 주며 거미줄처럼 얽혀 있습니다. 한 줄을 건드리면 멀리 떨어진 다른 줄의 동작이 바뀝니다. 코드는 마치 하나의 살아있는 유기체처럼 움직입니다. 이 복잡함 속에서 일어날 수 있는 경우의 수는, 조금만 규모가 커져도 천문학적으로 불어납니다.

그래서 어떤 프로그램이 ‘모든 경우에 옳다’는 것을 끝까지 확인하는 일은, 사실상 불가능에 가깝습니다. 들어올 수 있는 입력은 끝이 없고, 벌어질 수 있는 상황의 조합은 다 헤아릴 수 없습니다. 개발자가 미리 그려본 경우들 외에는, 언제나 미처 생각하지 못한 경우가 남아 있습니다. 사용자는 개발자가 상상조차 못 한 방식으로 프로그램을 쓰고, 코드를 짤 때의 전제는 세월이 지나면 그대로 남아 있지 않습니다. 버그란 바로 그 ‘미처 생각하지 못한 곳’에서 튀어나옵니다. 그것도 게을러서가 아닙니다. 애초에 모든 자리를 다 들여다보는 일이 사람의 능력 밖이니까요.

그리고 이것은 비단 소프트웨어만의 운명이 아닙니다. 손으로 만질 수 있는 정교한 기계에도, 촘촘하게 짜인 무형의 제도와 계획에도, 만든 이가 미처 내다보지 못한 빈틈은 늘 남습니다. 무언가가 어느 경계 이상으로 복잡해지는 순간, 그것을 만든 사람의 머리로 그 전부를 빈틈없이 장악하는 일은 더 이상 가능하지 않습니다. 완벽이 어려운 것은 우리가 부족해서가 아니라, 복잡함이라는 것의 본래 성질이 그러하기 때문입니다.

버그를 곁에 두고도 살아가야 할 때

그래서 개발자들은 일찍이 한 가지를 받아들입니다. 완벽한 프로그램은 없다는 것입니다.

아무리 뛰어난 개발자도 실수를 합니다. 아무리 공들여 만든 소프트웨어에도 버그는 있습니다. 이것은 게으름이나 무능의 문제가 아니라, 사람의 손으로 무언가를 만드는 일의 피할 수 없는 조건입니다. 그래서 개발자들은 버그를 없앨 수 있는 것으로 여기지 않습니다. 늘 곁에 함께 있는 것으로 받아들이지요. 버그가 없기를 바라는 대신, 버그가 있다는 것을 전제로 일합니다. 미리 찾아보고, 어디서 무슨 일이 있었는지 기록해두고, 터졌을 때 잘 대처할 채비를 합니다. 완벽을 꿈꾸는 대신, 불완전함을 다루는 법을 익히는 것입니다.

저는 다시 한 번 이 코드 너머에 있는 우리의 삶을 돌아봅니다. 우리는 흔히 결함이 하나도 없는 상태를 목표로 삼습니다. 빈틈없는 계획, 흠 없는 결과, 실수 없는 하루를요. 그러나 복잡한 무언가를 만들고 이뤄가는 일에는, 아무리 공들여도 어딘가 불완전함이 따라붙기 마련입니다. 그것을 부끄러운 실패로만 여기며 자책하는 동안에는, 정작 그 불완전함을 마주하고 다루는 일에는 좀처럼 손을 대지 못하곤 합니다.

그 불완전함을 어떻게 받아들이느냐에 따라, 우리를 주눅 들게 할 수도 있고, 오히려 자유롭게 하기도 합니다. 완벽한 프로그램이 없다는 것은, 완벽한 사람도 없다는 말과 같기 때문입니다. 무언가를 만들고 살아가는 일에 실수와 결함이 따르는 것은 흠이 아니라 자연스러운 일입니다. 중요한 것은 결함이 하나도 없는 것이 아니라, 결함이 있음을 인정하고 그것과 더불어 나아가는 법을 익히는 것이기도 합니다. 버그가 박멸해야 할 적이 아니라 곁에 두고 가는 것이듯, 우리 삶에서 뜻대로 되지 않는 크고 작은 일들 역시 우리를 덮친 재앙은 아닙니다. 그것은 다만, 무언가를 만들고 이뤄가는 사람이라면 누구나 안고 가는, 피할 수 없는 동반자입니다. 단 하나의 버그도 만들지 않겠다는, 이룰 수 없는 목표에 매달리기보다는, 버그가 터졌을 때 담담히 잘 대처하는 힘을 기르고 준비해 보는 건 어떨까요.

See Also

Graph View

댓글 (0)

아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요.