ComplexityTaming

주니어 개발자들을 위한 패턴 언어 - 코드의 덩어리를 쪼개고 이름을 붙여 복잡성의 야수를 길들이는 법

The Story: The Gordian Knot vs. The Organized Toolbox

두 명의 개발자, 민수와 하나가 '복잡한 배송료 계산 엔진'을 다루고 있다.

민수의 코드 (The Gordian Knot): 민수의 계산 함수는 300줄이 넘는다. 국가별 세율, 무게당 단가, 부피당 단가, 할인 프로모션, 주말 할증 로직이 거대한 if-elsefor 루프 속에 뒤섞여 있다. "로직이 워낙 복잡해서 어쩔 수 없어요." 민수 자신도 코드를 수정할 때마다 어디가 어떻게 영향을 받을지 몰라 전전긍긍한다. 작은 기능 하나를 추가하려고 해도 실타래처럼 엉킨 코드 전체를 읽어야 한다.

하나의 코드 (The Organized Toolbox): 하나는 복잡함을 인정하고 그것을 다루는 도구들을 꺼냈다.

  1. 분해(Decomposition): 거대한 함수를 calculateTax(), calculateBaseRate(), applyPromotions()로 쪼갰다.

  2. 이름 붙이기(Naming): 각 조각에 명확한 이름을 붙여 무엇을 하는지 드러냈다.

  3. 추상화(Abstraction): 배송 정책을 ShippingPolicy 인터페이스로 정의하여 새로운 정책을 추가하기 쉽게 만들었다.

하나는 복잡한 문제를 여러 개의 '단순한 문제'로 바꾸어 놓았다. 그녀의 코드는 부품들이 잘 정리된 도구함 같아서, 누구나 필요한 부분만 골라 이해하고 수정할 수 있었다.

Context

시스템이 OrganicGrowth를 통해 성장하면서, 특정 부분의 로직이 감당하기 힘들 정도로 복잡해졌다. 함수가 길어지고, 조건문이 중첩되며, 변수가 너무 많아진다.

일상적인 상황:

당신은 지금 복잡성이라는 야수에게 먹히기 직전이다.

Problem

관리되지 않는 복잡성은 개발자의 인지 한계를 넘어서고, 결국 시스템의 유지보수를 불가능하게 만든다.

Solution

추상화, 분해, 네이밍, 관심사 분리라는 "복잡성 길들이기 도구"를 사용하여 문제를 다룰 수 있는 크기로 쪼개라.

복잡성을 없앨 수는 없지만, 그것을 **정리**할 수는 있다.

Principle 1: Divide and Conquer (분할 정복)

큰 문제는 작은 문제들로 나누어라.

Principle 2: Names as Abstractions (이름을 통한 추상화)

복잡한 로직 뒤에 이름을 붙여 숨겨라.

Principle 3: Separation of Concerns (관심사 분리)

서로 다른 종류의 지식은 섞지 마라.

Principle 4: Encapsulate Volatility (변하는 것을 캡슐화하라)

자주 바뀔 것 같은 부분은 따로 떼어내어 감싸라.

Real Examples

Example 1: Nested If-Else vs. Guard Clauses

민수:

if (user != null) {
    if (user.isActive()) {
        if (order.isValid()) {
            process(order);
        }
    }
}

하나 (Guard Clauses):

if (user == null) return;
if (!user.isActive()) return;
if (!order.isValid()) return;

process(order);

복잡한 중첩을 제거하여 사고의 흐름을 직선으로 만들었다.

Example 2: Extracting a Policy Object

배송비 계산 로직이 상품 종류, 거리, 무게에 따라 복잡하게 얽혀 있다면, 이를 FeeCalculator라는 객체로 추출하여 복잡성을 그 안에 가둔다.

Common Pitfalls

"Premature Abstraction" (성급한 추상화)

문제가 충분히 복잡해지기도 전에 미리 레이어를 나누는 것.

"Leaky Abstraction" (새는 추상화)

추상화를 만들었지만, 내부 세부 사항이 밖으로 새어 나오는 것.

Over-splitting (과도한 쪼개기)

너무 잘게 쪼개서 오히려 전체 흐름을 보기 힘든 경우.

Connection to Other Patterns

Signs of Success

The Ultimate Insight

소프트웨어 공학의 역사는 복잡성을 다루는 도구를 개발해온 역사다.

우리는 복잡한 세상을 다루기 위해 프로그래밍을 한다. 하지만 코드가 세상보다 더 복잡해져서는 안 된다. 문제를 쪼개고, 이름을 붙이고, 경계를 세워라. 복잡성을 통제할 수 있을 때, 비로소 당신은 시스템의 주인이 된다.


CategoryPatternLanguage CategoryProgramming CategoryDesign CategoryRefactoring