NamesAsDesign

주니어 개발자들을 위한 패턴 언어 - 네이밍을 설계 활동으로 다루어 개념을 명확히 하는 방법

The Story 1: The Search for the Right Name (Programming)

주니어 개발자 민수는 주문 처리 시스템을 작성하고 있었다. 그는 변수 이름을 짓다가 막혔다.

def process(data):
    x = data['items']
    y = 0
    for i in x:
        y += i['price'] * i['qty']
    return y

"이건 너무 못생겼어..." 민수는 생각했다. 30분 동안 고민한 끝에 이름을 아주 길게 고쳤다. calculate_order_total_amount_including_all_items(order_data). 하지만 코드 리뷰에서 하나가 말했다.

"민수님, 명확함은 길이가 아니라 문맥에서 나와요. 봐요."

class Order:
    def total(self):
        return sum(item.subtotal() for item in self.items)

class Item:
    def subtotal(self):
        return self.price * self.quantity

# 사용할 때
order = Order(...)
payment.charge(order.total())

"봐요, order.total()이라고 쓰면 Order의 total이라는 게 명확하죠? 문맥이 이름을 완성하는 거예요. 그리고 Item.subtotal()Item의 소계라는 게 바로 보이지요? 이름은 혼자 존재하는 게 아니라 관계 속에서 의미를 갖는 거예요. 이름 짓기는 단순히 라벨을 붙이는 게 아니라, 좋은 설계를 반영하는 설계 활동 그 자체입니다."

The Story 2: The Baby's Name (Ordinary Life)

민수와 하나는 곧 태어날 아기의 이름을 고민하고 있다.

민수의 작명 (The Functional Name): 민수는 실용적인 이름을 원한다. "우리 첫째니까 그냥 '민수 주니어 1호'라고 부르면 어때? 누가 봐도 내 아들인 걸 알 수 있잖아." 민수에게 이름은 단순히 대상을 식별하기 위한 라벨일 뿐이었다. 하지만 '1호'라는 이름은 아이의 개성이나 가족 안에서의 정체성을 전혀 담아내지 못했다.

하나의 작명 (The Design Name): 하나는 이름이 아이의 삶을 설계하는 첫 번째 단추라고 생각한다. "아이의 이름은 성(Last name)과 조화로워야 하고, 나중에 자라서 사회에서 불릴 때의 느낌도 고려해야 해." 하나는 아이가 평생 불릴 문맥을 상상하며 이름을 골랐다. "밝게 빛나라는 뜻의 '윤(潤)'을 넣자. 우리 가족의 따뜻한 분위기와도 잘 어울려." 이름이 정해지자 아이의 방을 어떻게 꾸밀지, 어떤 옷을 입힐지 같은 '설계'가 자연스럽게 뒤따랐다. 이름은 단순한 라벨이 아니라, 존재의 본질을 규정하는 설계의 시작임을 하나는 알고 있었다.

Context

당신은 코드를 작성하면서 변수, 함수, 클래스, 모듈에 이름을 붙여야 한다. 이름은 코드의 모든 곳에 있고, 코드를 읽는 사람이 가장 먼저 보는 것이다.

당신은 LanguageBuilding을 통해 도메인 언어를 만드는 것의 중요성을 알고, MetaphorThinking을 통해 은유가 이해를 돕는다는 것을 안다. 이제 그 언어를 구성하는 단어 하나하나를 만드는 단계다.

일상적인 상황:

Problem

초보 프로그래머는 네이밍을 단순한 라벨링으로 취급한다. 어떤 이는 너무 빨리 못생긴 이름을 붙이고, 어떤 이는 오래 고민하지만 결과는 여전히 좋지 않다.

The Naming Dichotomy

주니어는 두 극단 사이를 오간다:

The Fundamental Misunderstanding

Phil Karlton은 "컴퓨터 과학에서 어려운 것은 딱 두 가지뿐이다. 캐시 무효화와 이름 짓기"라고 했다. 왜 네이밍이 어려운가?

The Isolation Problem

주니어는 이름을 고립되어 생각한다. 하지만 이름은 관계망 속에 존재한다. order.total()이라고 쓰면 'Order'라는 부모가 문맥을 제공하기 때문에 짧은 이름으로도 충분히 명확해진다. 이름의 품질은 부모, 형제, 자식과의 관계 속에서 결정된다.

The Surface of Design

이름은 설계의 표면이다. 나쁜 이름은 종종 나쁜 설계를 반영한다. 이름 짓기가 어렵다는 것은 개념이 불명확하거나, 책임이 잘못 분배되었거나, 추상화가 잘못되었다는 신호다.

Name as Concept

이름은 단순한 라벨이 아니라 개념 그 자체다. itemsshopping_cart라고 부르는 순간, 단순한 리스트가 쇼핑이라는 맥락을 가진 개념으로 변한다. 이름을 바꾸면 생각이 바뀐다.

Names vs Documentation

좋은 이름은 주석보다 가치 있다. "Clean code is when each function does pretty much what you expected." (Ward Cunningham). 그 예상을 만드는 것이 바로 이름이다.

Solution

네이밍을 사고를 명확하게 하고 추상화를 드러내는 설계 활동으로 다뤄라. 좋은 이름은 문맥 속에서 평가되고, 관계 속에서 의미를 갖는다. 이름은 개념이고, 좋은 이름은 좋은 설계를 반영한다.

Principle 1: Names in Context (Embedding)

이름은 고립되어 평가할 수 없다. 문맥에 embedding하여 평가하라.

Principle 2: Relational Quality (Playing Along)

좋은 이름은 "잘 어울린다" - 형제, 부모, 자식과 조화롭게.

Principle 3: Two Spaces - Problem and Solution

TwoWorlds를 기억하라. 좋은 이름은 문제 공간과 해결 공간을 모두 잘 표현한다.

Principle 4: Name as Concept (Conceptualization)

이름 짓기는 개념화하기다. 명확한 이름 = 명확한 개념. 이름을 찾는 과정은 개념을 발견하는 과정이다. data -> user_data -> user_profile로 이름이 명확해지는 과정은 설계가 정교해지는 과정과 일치한다.

Principle 5: Names > Documentation

좋은 이름은 주석을 불필요하게 만든다. "The proper use of comments is to compensate for our failure to express ourselves in code." (Robert C. Martin). 이름으로 표현하지 못해서 주석을 쓰는 것이다.

Principle 6: Metaphor and Analogy

MetaphorThinking - 좋은 은유는 좋은 이름을 만든다. Stack.push(), Queue.enqueue(), Stream.flush() 처럼 은유가 직관적 이해를 돕는다.

Principle 7: Semantic Network

LanguageBuilding - 이름들은 의미 네트워크를 형성한다. total, subtotal, tax - 이 단어들은 서로 관계를 형성하며 하나를 보면 다른 것을 예상할 수 있게 한다.

Real Examples

Example 1: From Generic to Specific

process(data) -> process_numbers(numbers) -> double_prices(prices) -> apply_inflation(prices). 각 단계마다 개념이 명확해진다.

Example 2: Context Makes Meaning

같은 size()라도 File.size()는 바이트 크기, Shirt.size()는 "M", "L", List.size()는 원소 개수를 의미한다. 문맥이 의미를 만든다.

Example 3: Siblings Harmony

UserRepositorycreate, read, update, delete 처럼 일관된 패턴은 예측 가능성을 만든다.

Example 4: Real Naming Session

엉성한 func(x, y) 로직을 find_passing_students(scores, 60)로 리팩토링하는 과정은 이름이 진화하면서 설계가 개선되는 전형적인 모습이다.

Example 5: Metaphor Power

Factory(공장), Builder(건축가), Observer(관찰자) 등 디자인 패턴의 이름은 은유를 통해 복잡한 설계를 한 번에 이해시킨다.

Example 6: Names Reveal Design Issues

UserManagerControllerHandlerService 처럼 이름 짓기가 어렵다면, 그것은 클래스가 너무 많은 일을 하고 있다는 설계적 결함의 신호다.

The Naming Process

Process 1: Start Concrete, Then Abstract

일반적인 것부터 시작하지 마라. prices -> doubled_prices 처럼 구체적인 것부터 시작하라.

Process 2: Let Context Emerge

이름을 먼저 짓지 마라. WorkingFirst 원칙에 따라 일단 작동하게 만들고, 사용 문맥 속에서 더 나은 이름을 발견하라.

Process 3: Refactor Names

이해도가 깊어지면 이름도 리팩토링하라. LivingVocabulary 패턴에 따라 어휘를 지속적으로 정제하라.

Process 4: Read Aloud Test

이름을 소리 내어 읽어보라. "Order야, total 해줘"가 자연스러운지 확인하라.

Process 5: Consistency Check

비슷한 개념은 비슷한 패턴으로 명명하여 일관성을 확인하라.

Common Pitfalls

Pitfall 1: Premature Long Names

명확하려다 장황해지는 것. 문맥을 활용하여 길이를 줄여라.

Pitfall 2: Abbreviations

proc_usr_ord 처럼 이해를 방해하는 약어를 피하라. 보편적인 약어(id, url)만 허용하라.

Pitfall 3: Inconsistent Vocabulary

User, Customer, Client를 혼용하지 마라. 하나의 개념은 하나의 이름으로 통일하라.

Pitfall 4: Type in Name

strName, arrUsers 처럼 타입 정보를 이름에 넣지 마라. 의미에 집중하라.

Pitfall 5: Noise Words

Manager, Processor, Data 처럼 의미 없는 단어(소음)를 제거하라.

Pitfall 6: Naming in Isolation

문맥 없이 이름을 평가하지 마라. get()이 좋은 이름인지는 그것이 어디에 속해 있느냐에 달렸다.

Connection to Other Patterns

Signs of Success

The Ultimate Insight

이름은 코드의 가장 중요한 문서이며, 설계의 표면이자 개념 그 자체입니다.

이름을 짓는 것은 단순한 라벨링이 아니라, 당신의 사유를 정제하는 설계 활동입니다. 좋은 이름을 찾기 어렵다면 설계를 다시 보십시오. 이름을 설계하십시오. 그러면 코드가 스스로 당신에게 진실을 말할 것입니다.


CategoryPatternLanguage CategoryProgramming CategoryDesign CategoryNaming CategoryCleanCode

NamesAsDesign (last edited 2025-12-30 09:07:55 by 정수)