컬리의 법칙: 하나만 해라

등록일: 2014. 10. 13

팀 오팅거Tim Ottinger는 ‘어마어마한 변수의 부족에서 살아남기Outliving the Great Variable Shortage’에서 컬리의 법칙Curly’s Law을 끄집어냈다.

변수는 어떤 하나의 값, 오직 하나의 값만을 의미해야 한다. 변수는 어떤 상황에서는 이것을 의미하고, 다른 상황에서는 저것을 의미하면 안 된다. 변수는 두 가지를 동시에 의미하지 않아야 한다. 그것은 바닥청소용 세제와 후식 위에 올리는 토핑을 동시에 의미할 수 없다. 그것은 언제나 어떤 하나의 의미만 담고 있어야 한다. 그리고 언제나 그것만을 의미해야 한다.

위대한 배우 잭 팰랜스Jack Palance는 1991년에 코미디 영화 『시티 슬릭커스City Slickers에서 황혼의 카우보이 컬리 와쉬번Curly Washburn을 연기했다. 컬리의 법칙은 영화에 등장하는 대화를 통해 정의된다.

컬리: 인생의 비밀이 뭔지 아나?
컬리: 이거야. [한 손가락을 들어올린다]
미치: 자네 손가락?
컬리: 한 개. 오직 한 개. 그것만 죽어라 파는 거야. 나머진 다 쓸모없는 것들이지.
미치: 그 ‘한 개’가 뭔데?
컬리: [미소를 지으며] 그건 스스로 알아내야지.

컬리의 법칙인 ‘하나만 해라’는 현대 소프트웨어 개발의 몇몇 핵심 원칙에 반영돼 있다.

반복하지 말라Don’t Repeat Yourself

똑같은 것을 표현하는 방법이 하나 이상 있다면 언젠가 두세 개의 표현 방법들이 서로에게 방해가 되는 순간이 올 것이다. 그렇지 않더라도 그것들을 수정해야 하는 필요성이 대두되면 모두를 따로 관리해야 하는 상황 탓에 문제가 야기될 것이다. 유연하고 유지보수하기 쉬운 소프트웨어를 만들고 싶다면 반복하지 않는 것이 중요하다.

한 번, 오직 한 번만Once and Only Once

행위에 대한 선언은 모두 반드시 한 번, 오직 한 번만 해야 한다. 코드를 리팩터링할 때 이것을 가장 중요한 목표라고 볼 수 없다면, 적어도 가장 중요한 목표 중 하나라고는 볼 수 있다. 설계 목표는 행위에 대한 선언이 중복돼 있는 부분을 제거하는 것인데, 행위에 대한 선언이 중복된 부분을 합치거나 여러 곳에 작성돼 있는 비슷한 코드를 단 하나의 추상화로 대체함으로써 제거한다.

진실의 한 단면Single Point of Truth

반복된 코드는 비일관성과 힘을 합쳐서 미묘하게 잘못된 코드를 낳는다. 여러 곳에서 반복되는 코드를 모두 변경해야 할 때 일부만 변경하고 마는 경우가 생기기 때문이다. 그러한 코드의 반복은 코드를 어떤 식으로 구성할지를 제대로 생각하지 않고 코드를 작성했다는 사실을 반증한다. 중복된 코드가 눈에 띌 때마다 그것을 위험신호로 보면 된다. 복잡성은 비용을 수반한다. 그 비용을 한 번 이상 지불하지 마라.

컬리의 법칙이 명백히 정규화나 중복 제거에 적용되는 것은 틀림없지만 ‘하나만 해라’라는 법칙은 위에서 간략하게 소개한 중복을 피하고 코드를 한 번만 작성하라는 원칙을 다양한 방식으로 변주하는 여러 표현에 비해 약간 더 미묘한 의미를 내포하고 있다. 하나만 하라는 원리는 그러한 변주보다 깊은 원칙을 담고 있다. 밥 마틴Bob Martin은 이것을 단일 책임 원칙The Single Responsibility Principle이라고 부른다.

단일 책임 원칙에서는 어떤 클래스를 변경하는 이유는 반드시 단 하나여야 한다고 말한다. 예를 들어 다음 클래스를 생각해보자.

class Employee {
    public Money calculatePay()
    public void save()
    public String reportHours()
}

이 클래스는 변경될 수 있는 이유가 무려 세 가지나 있기 때문에 SRP를 위배한다.

  1. 급여 계산과 관련된 비즈니스 규칙
  2. 데이터베이스 스키마
  3. 시간을 보고하는 문자열의 형식

우리는 한 클래스가 세 가지나 되는 서로 완전히 다른 이유에 영향을 받기를 원하지 않는다. 회계부서에서 업무시간을 보고하는 형식을 바꿀 때마다, 혹은 DBA가 데이터베이스의 스키마를 변경할 때마다, 그리고 관리팀에서 급여를 계산하는 방식을 바꿀 때마다 이 클래스의 코드를 변경하고 싶지는 않다. 이렇게 하는 대신 우리는 이 클래스를 세 개의 독립적인 클래스로 분할해서 각 클래스에 대한 변경이 서로에게 아무런 영향을 미치지 않도록 만들고자 한다.

컬리의 법칙은 특정한 부분의 코드에 명확하게 정의된 단 하나의 목표를 부여하고자 하는 것이다. 하나만 해라. 그 정도면 충분히 명확하다. 이렇게 단 하나를 선택하는 행위를 통해 당신은 달리 선택할 수 있었던 무한한 가능성의 우주를 포기하고 배제한다. 그리하여 컬리의 법칙은 당신의 코드가 무엇을 할지가 아니라 무엇을 하지 않을 것인가를 의식적으로 선택하는 과정이기도 하다. 하지 않을 것을 정하는 일은 무엇을 할지 정하는 일보다 훨씬 힘들다. 그것은 소프트웨어 개발자가 가지고 있는 자연스럽고 일반적인 경향에 전적으로 어긋나기 때문이다. 그러한 결정을 내리는 것은 코드를 완전히 분해하는 것을 의미할 수 있고, 전통적인 OOP 규칙을 위배하는 것일 수도 있고, 혹은 코드 안에 무려 중복을 야기하는 것일 수도 있다. 그것은 두 걸음 앞으로 나아가기 위해 한 걸음 뒤로 물러서는 것에 해당한다.

각각의 변수, 코드 한 줄, 함수, 클래스, 프로젝트는 오직 하나의 일만 수행해야 한다. 그렇지만 안타깝게도 우리는 그 하나가 무엇인지를 마지막 순간에 이르기까지 알지 못하는 경우가 대부분이다.