제품을 만든다는 건 Kludge를 쌓는 것이다

제품을 만든다는 건 Kludge를 쌓는 것이다

제품을 만든다는 건 Kludge를 쌓는 것이다

마감이 이틀 남았는데 고객사 한 곳이 자기 회사 화면만 따로 보여 달라고 합니다. 기획 단계에서는 나오지 않았던 요청입니다. 제대로 받으려면 설정 구조부터 다시 만들어야 하는데, 이틀 안에는 못 합니다. 그래서 그 고객사일 때만 화면을 바꾸는 조건문을 한 줄 넣습니다. 테스트해 보니 문제없어서 그대로 배포합니다. 그 한 줄은 그 뒤로도 코드에 남습니다.

이런 코드를 kludge라고 합니다. 이 단어가 활자로 남은 이른 예로 1962년 Jackson Granholm의 글이 자주 거론되는데, 거기 실린 정의는 다음과 같습니다.

An ill-assorted collection of poorly-matching parts, forming a distressing whole.

안 맞는 부품을 아무렇게나 모아 만들어서 보고 있으면 괴로운 물건이라는 뜻입니다. Granholm은 그렇게 만들어진 물건 전체를 kludge라고 불렀습니다. 요즘은 그 안에 들어간 임시 처리 하나하나를 kludge라고 부르는 일이 많아서, 이 글에서도 그렇게 쓰겠습니다.

저도 한때는 kludge를 실력이 부족하다는 표시로 여겼습니다. 설계를 잘했으면 안 생겼을 코드라고 생각했습니다. 제품을 몇 개 만들고 나서는 생각이 달라졌습니다. 어느 제품이든 처음 기획으로는 대응할 수 없는 상황이 꼭 생겼고, kludge는 대개 거기서 나왔습니다.

그렇다고 아무렇게나 만들어도 된다는 얘기는 아닙니다. 시작할 때 알 수 있었고 당연히 챙겼어야 할 것을 빠뜨렸다면 그건 그냥 잘못 만든 겁니다. kludge는 미리 알 길이 없던 상황을 만났을 때, 싸게 처리한다는 걸 알고서 고른 방법입니다.

처음부터 기능과 화면을 모두 설계할 수는 없었습니다

처음 제품을 만들 때는 기능 목록과 화면, 예외 처리까지 문서로 끝내 놓으면 그다음은 만들기만 하면 된다고 믿었습니다. 잘 안 되는 건 제 설계 실력이 모자라서라고 여겼습니다. 몇 번 해 보니 실력과 상관없이 처음에 다 설계하는 건 불가능했습니다.

제품 주변이 가만있지 않아서입니다. 고객이 바뀌고, 같은 고객도 시간이 지나면 다른 걸 원합니다. 경쟁사가 뭔가를 내놓으면 고객이 제품을 보는 기준이 통째로 달라지기도 합니다. 설계도를 다 그렸을 즈음엔 그 설계도로 맞추려던 요구가 이미 바뀌어 있습니다. 시작할 때 모든 걸 고려하는 건 성실하게 해도 불가능합니다.

제품은 요구가 바뀔 때마다 기능을 추가하고 고치며 진화합니다

1977년 분자생물학자 François Jacob은 진화가 일하는 방식을 땜장이(bricoleur)에 빗댔습니다. 설계자는 목표를 정하고, 필요한 재료를 새로 구하고, 설계도에 맞춰 만듭니다. 진화는 이미 있는 부품을 가져다 엮어서 당장의 문제를 해결합니다.

제가 제품을 만들며 실제로 하는 일도 대부분 이런 식입니다. 고객이 불편하다고 하면 기능을 추가하고, 요구가 바뀌면 있던 기능을 고쳐서 다시 씁니다. 그럴 때마다 kludge가 하나씩 생깁니다. 생물이 환경에 맞춰 바뀌듯 제품은 고객과 요구의 변화에 맞춰 바뀌고, kludge는 그 과정에서 생깁니다.

예전 요구에 맞춰 넣은 코드는 요구가 바뀐 뒤에도 남습니다

kludge는 넣기만 하고 빼는 일은 드물어서, 예전 요구에 맞춰 넣은 코드가 요구가 바뀐 뒤에도 그대로 남습니다. 기린 몸에도 이런 kludge가 있습니다. 뇌에서 후두로 가는 되돌이후두신경은 후두가 가까이 있는데도 목을 따라 심장 근처까지 내려갔다가 다시 올라옵니다. 기린은 이 우회로만 4.6미터쯤 됩니다. 옛 환경에서는 그 경로가 가장 나았을 텐데, 지금은 바꿀 방법이 없어 그대로 남았습니다.

제품에도 이런 코드가 있습니다. 예전 고객이나 예전 요구 때문에 넣었는데 이제는 아무도 쓰지 않습니다. 그런데 겁이 나서 아무도 지우지 못합니다. 오래된 제품일수록 이런 코드가 겹겹이 있습니다.

kludge를 계속 넣든 구조를 새로 만들든 비용을 치릅니다

기린과 달리 제품은 처음부터 다시 만들 수 있습니다. 마음만 먹으면 쌓인 코드를 다 지우고 새로 만들 수 있습니다. 그러면 kludge 없는 깨끗한 제품을 얻을 수 있을까요.

kludge를 계속 넣으면 코드가 지저분해지고, 기능을 추가하기가 점점 어려워집니다. 흔히 기술 부채라고 부르는 빚입니다. 새로 만드는 데도 비용이 듭니다. 잘 돌던 걸 멈추고 사람을 투입해야 하고, 그동안은 새 기능을 만들지 못합니다. 둘 다 빚이고, kludge를 넣으면 코드로, 새로 만들면 시간과 노동으로 갚습니다. 지금 당장은 kludge가 쌉니다.

PM: “이번 고객만 예외로 막아 둘 수 있어요?”

개발자: “되긴 하는데, 나중에 여기 손대기 싫어질 거예요.”

지금 kludge로 싸게 끝내고 넘어갈지, 나중에 더 큰 비용을 들여서라도 제대로 할지 정해야 하는데, 미리 정해진 답은 없습니다.

어느 kludge가 옳았는지는 고객과 요구가 한 번 더 바뀌어 봐야 압니다

어디는 임시로 처리하고 어디는 멈춰서 제대로 할지 미리 알려 주는 규칙이 있으면 편하겠지만, 그런 규칙은 만들 수가 없습니다. 어떤 kludge가 잘한 선택이었는지는 다음 환경 변화를 한 번 겪어 봐야 알 수 있기 때문입니다.

처음의 조건문 한 줄로 생각해 보면, 다른 기능이 의존하지 않는 코드에 그 조건문이 있었다면 적은 비용으로 끝난 좋은 kludge입니다. 그 조건문이 하필 나중에 만든 여러 기능이 의존하는 코드, 곧 제품의 기둥에 있었다면 빚에 이자가 생깁니다. 그 코드가 기둥인지 변두리인지는 고객과 요구가 몇 번 바뀌는 동안 그 코드를 얼마나 자주 고치게 되는지 봐야 알 수 있습니다.

진화의 적합도도 그렇게 정해집니다. 어떤 형질이 유리할지 정해 두고 만드는 과정은 없습니다. 형질이 먼저 생기고, 그 형질을 가진 생물이 살아남은 뒤에야 유리했다는 걸 알게 됩니다. 적합도도 지나고 나서야 확인됩니다.

진화와 달리 사람은 짐작이라도 할 수 있습니다. 노련한 엔지니어나 디자이너는 어디가 기둥이 될지 어느 정도 압니다. 결제, 인증, 데이터 모델처럼 다른 기능이 많이 의존하는 코드에 kludge를 넣어 두면 나중에 비싸진다는 걸 겪어 봐서입니다. 그래도 그 짐작이 빗나갈 때가 있습니다.

그러니 시작하는 날 아무리 오래 고민해도 고를 답이 없습니다. kludge를 넣을지 제대로 고칠지, 둘 가운데 무엇이 맞았는지는 제품이 바뀐 환경을 한 번 더 겪어야 정해집니다.

kludge를 아예 안 넣으려 하면 기술 부채보다 더 큰 문제가 생깁니다

kludge를 아예 안 넣으려는 사람들도 있습니다. 저는 이런 태도가 빚보다 더 위험하다고 봅니다. 겉으로는 서로 정반대로 일하는 사람들이 여기에 함께 들어갑니다.

어떤 사람은 요구가 하나 들어올 때마다 구조부터 다시 설계하자고 합니다. 임시로 처리하고 넘어가는 걸 견디지 못하고, 전부 다시 만들어야 마음이 놓입니다. 완벽하게 만들기 전에는 내보낼 수 없다는 결벽입니다.

반대편에는 처음 기획을 끝까지 고집하는 사람이 있습니다. 고객이 다른 걸 원해도 처음 설계대로 가야 한다며 kludge를 넣는 걸 거부합니다.

이런 사람들이 그렇게 하는 이유는 대개 자존심이나 불안입니다. 깔끔하게 설계하거나 처음 설계를 지켜 내야 실력이라고 믿고, 임시 코드를 누가 볼까 신경 쓰이고, 설계를 바꾸면 처음 판단이 틀렸다고 인정하는 것 같아서입니다. 그래서 방향을 바꿔야 할 때도 못 바꿉니다.

다시 설계하는 사람도 처음 설계를 고집하는 사람도, kludge를 넣어 두고 상황을 한 번 더 지켜보는 단계를 건너뜁니다.

kludge가 생기는 동안 제품은 바깥 변화에 반응하고 있습니다. 그 단계를 건너뛴 제품은 세상이 바뀌는 동안에도 처음 모습 그대로입니다. 이건 빚보다 더 큰 문제입니다. 진화를 멈춘 제품은 조금씩 뒤처지다가 사라집니다.

kludge가 쌓이다 보면 부분적으로 고쳐서는 해결되지 않고 구조를 통째로 다시 설계해야 하는 때가 실제로 옵니다. 그때 새로 만드는 건 괜찮습니다. 고객과 요구가 바뀔 때마다 같은 코드를 다시 고치게 돼서 새로 만드는 거라면 제품이 진화하는 과정입니다. 임시 코드가 보기 싫어서 앞당긴 리팩토링이라면 결벽입니다.

요즘은 kludge를 기록해 두고, 다시 만들어야 할 때는 미루지 않습니다

kludge를 넣을 때는 기록을 남깁니다. 이게 임시 처리라는 것, 어떤 가정을 전제로 싸게 처리했는지, 그 가정이 깨지면 다시 고쳐야 한다는 것을 적어 둡니다. 부끄럽다고 숨기면 나중에 아무도 그게 빚인 줄 모르고, 그사이 이자만 늘어납니다.

다시 만들어야 할 때가 오면 미루지 않습니다. 기둥인지 변두리인지 아직 모르는데 미리 새로 만드는 건 낭비입니다. 하지만 고객과 요구가 바뀔 때마다 같은 코드를 다시 고치게 돼서 새로 만들 때가 됐는데도, 초기 설계를 지키려고 미루면 손해가 더 큽니다. 큰 리팩토링을 하게 됐다면 제품이 아직 살아서 바뀌고 있다는 뜻이니 실패로 볼 이유가 없습니다.

처음 설계가 맞았는지는 이제 잘 묻지 않습니다. 처음 설계는 그때 있던 정보로 세운 가설이었고, 환경이 바뀌면 언젠가 어긋납니다. 그 대신 그동안 우리가 무엇을 배웠는지, 이 제품이 지금 고객에게 실제로 쓸모가 있고 돈을 벌고 있는지를 묻습니다.

제품은 이렇게 배운 만큼 고쳐 가며 진화합니다. 잘 만든 제품인지는 kludge 개수나 처음 설계를 지켰는지로 판단하지 않습니다. 만든 사람이 무엇을 배웠는지 알고, 다시 만들어야 할 때 미루지 않았고, 고객이 돈을 내고 쓰고 있다면 잘 만든 제품입니다.

이 글, 어떠셨어요?

이 글에 오류가 있나요?

사실이 틀렸거나 오탈자, 깨진 링크를 발견하셨다면 알려주세요. 확인하고 고치겠습니다.