ComplexityTaming

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

The Story 1: The Gordian Knot vs. The Organized Toolbox (Programming)

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

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

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

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

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

  3. 추상화(Abstraction): 배송 정책을 인터페이스로 정의하여 새로운 정책을 추가할 때 기존 코드를 건드리지 않게 만들었다.

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

The Story 2: The Messy Pantry (Ordinary Life)

민수와 하나는 자취방의 '식료품 저장실(Pantry)'을 정리하기로 했다.

민수의 정리 (The Pile): 민수는 모든 식료품을 그냥 선반에 차곡차곡 쌓아두었다. "공간을 아끼려면 이게 최선이야." 하지만 요리를 하려 할 때마다 민수는 고통받았다. 간장을 찾으려면 밀가루 포대를 들어내야 했고, 유통기한이 지난 통조림이 구석에서 썩어가고 있었다. 민수에게 주방은 들어가기 싫은 혼돈의 장소였다.

하나의 정리 (The Taming): 하나는 분류부터 시작했다.

  1. 범주화: 양념류, 곡물류, 통조림류로 구역을 나누었다. (관심사 분리)

  2. 용기 사용: 봉지에 든 가루들을 투명한 용기에 담고 라벨을 붙였다. (캡슐화와 네이밍)

  3. 계층 구조: 자주 쓰는 소금은 앞에, 가끔 쓰는 향신료는 뒤에 배치했다.

정리가 끝난 후, 하나는 눈을 감고도 원하는 재료를 1초 만에 꺼낼 수 있었다. 복잡한 대상을 다룰 수 있는 크기로 나누고 이름을 붙이는 것만으로도 평화가 찾아옴을 하나는 알고 있었다.

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-else 문을 '보호 구문(Guard Clauses)'으로 리팩토링하여 사고의 흐름을 직선으로 만드는 실천. 이는 뇌의 중첩 깊이를 획기적으로 줄여줍니다.

Example 2: Policy Objects

배송비 계산 로직이 상품 종류, 무게, 거리에 따라 복잡해질 때 이를 ShippingPolicy라는 객체로 추출하여 계산 엔진을 단순하게 유지한 사례.

Common Pitfalls

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

문제가 충분히 복잡해지기도 전에 미리 레이어를 나누는 것. DirectPath를 기억하십시오. 복잡성이 실제로 고통을 줄 때 비로소 도구를 꺼내십시오.

"Leaky Abstraction" (새는 추상화)

추상화를 만들었지만 내부 세부 사항이 밖으로 새어 나오는 것. 이름을 보고도 내부 코드를 들여다봐야만 한다면 그것은 실패한 추상화입니다.

Connection to Other Patterns

Signs of Success

The Ultimate Insight

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

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


CategoryPatternLanguage CategoryProgramming CategoryDesign CategoryRefactoring

ComplexityTaming (last edited 2025-12-30 09:15:04 by 정수)