LivingVocabulary
주니어 개발자들을 위한 패턴 언어 - 코드의 어휘를 살아있는 유기체처럼 다듬고 진화시키는 법
Contents
The Story 1: The Static Dictionary vs. The Evolving Language (Programming)
두 명의 개발자, 민수와 하나가 1년 된 '정산 시스템'의 코드를 수정하고 있다.
민수의 태도 (The Static Dictionary): 민수는 처음 정한 용어를 끝까지 고수한다. "처음 설계할 때 UserPoint라고 정했으니까, 지금 이게 사실상 '현금'처럼 쓰이더라도 이름을 바꾸면 안 돼요. 고치는 게 더 위험하니까요." 코드가 비즈니스의 변화를 따라가지 못하면서, 민수의 코드는 암호문이 되어갔다. 새로운 팀원은 UserPoint가 왜 Cash의 역할을 하는지 이해하기 위해 선임자에게 물어봐야만 했다. 지식은 코드 밖에서 썩어가고 있었다.
하나의 태도 (The Evolving Vocabulary): 하나는 비즈니스를 더 깊이 이해할 때마다 코드의 어휘를 바꾼다. "처음엔 UserPoint인 줄 알았는데, 써보니 이건 Balance(잔액)에 더 가깝네요. 이름을 바꿉시다." 하나는 AtomicCommit을 통해 용어를 하나씩 정제해 나갔다. 1년 뒤, 그녀의 코드는 도메인 전문가가 말하는 방식과 완벽하게 일치했다. 코드를 읽는 것만으로도 비즈니스 규칙이 머릿속에 들어왔다. 그녀의 어휘는 살아 움직이며 시스템과 함께 성장했다.
The Story 2: The Child's Name (Ordinary Life)
민수와 하나는 조카의 성장을 지켜보고 있다.
민수의 호칭 (The Fixed Label): 민수는 조카가 태어났을 때의 특징만 기억한다. 조카가 10살이 되었는데도 여전히 '애기'라고 부르거나, 갓난아기 때 쓰던 유아어만 사용한다. 조카는 이제 학교에 다니고 복잡한 감정을 표현하는 소년이 되었지만, 민수의 호칭은 과거에 멈춰 있다. 민수는 조카와 깊은 대화를 나누지 못하고 겉돌기만 한다.
하나의 호칭 (The Evolving Name): 하나는 조카의 정체성이 변할 때마다 그에 맞는 호칭과 언어를 선택한다. 처음에는 '복덩이'라는 태명으로, 그다음에는 이름으로, 조카가 자신의 개성을 드러내기 시작하자 '꼬마 발명가'라는 별명으로 불러주었다. 하나는 조카를 부르는 '어휘'를 조카의 실제 모습(Reality)에 끊임없이 동기화했다. 덕분에 하나는 조카와 가장 친밀한 관계를 유지하며 그의 성장을 가장 가까이서 지원할 수 있었다. 이름은 고정된 라벨이 아니라 관계의 깊이를 담는 그릇임을 하나는 알고 있었다.
Context
LanguageBuilding을 통해 도메인 언어를 구축하고 있고, OrganicGrowth로 시스템을 확장하고 있다. 시간이 흐르면서 시스템에 대한 이해가 깊어지고 비즈니스 상황이 변하는 시점이다.
일상적인 상황:
- 현재 사용 중인 변수나 클래스 이름이 어색하게 느껴진다.
- 도메인 전문가와 대화할 때 쓰는 단어와 코드 속 단어가 다르다.
- "이름을 바꾸고 싶은데 영향 범위가 너무 커서 포기한다"는 말을 자주 한다.
- 코드가 옛날의 낡은 지식을 담고 있어 오해를 불러일으킨다.
당신은 지금 죽은 언어(Dead Language)를 사용하여 살아있는 시스템을 표현하려 애쓰고 있다.
Problem
정체된 어휘는 코드의 가독성을 해치고, 개발자의 머릿속 모델과 실제 코드 사이의 간극을 벌린다.
지식의 부패: 비즈니스 개념은 변하는데 코드가 그대로면, 코드는 거짓말을 하게 된다.
의사소통 단절: 개발자끼리는 A라고 부르는데 코드는 B라고 적혀 있으면 실수가 잦아진다.
유지보수 저하: 이름이 의도를 정확히 반영하지 못하면 코드를 읽는 데 에너지가 낭비된다.
Solution
이해가 깊어짐에 따라 코드베이스에서 사용되는 어휘를 지속적으로 발전시키고 정제하라.
언어는 고정된 사전이 아니라, 사용하면서 자라나는 유기체다.
Principle 1: Ubiquitous Language (보편 언어의 유지)
코드의 용어를 도메인 전문가의 언어와 일치시켜라.
- 회의실에서 쓰는 단어가 바뀌었다면 코드도 즉시 바뀌어야 한다.
- 코드 자체가 최고의 명세서가 되게 하라.
Principle 2: Refactor Names Ruthlessly (이름 고치기를 두려워 말라)
더 적절한 단어를 찾았다면 즉시 고쳐라.
- 현대의 IDE는 안전한 이름 변경(Rename) 기능을 제공한다.
BabySteps를 통해 조금씩, 하지만 꾸준히 어휘를 교체하라.
Principle 3: Vocabulary as a Seed (어휘라는 씨앗)
좋은 이름 하나가 새로운 추상화를 이끌어낸다.
- 이름을 바꾸다 보면, 그 이름에 걸맞은 새로운 클래스나 함수가 필요함을 깨닫게 된다.
- 어휘의 정제가 설계의 진화로 이어진다.
Principle 4: Share the Dictionary (사전 공유하기)
팀 전체가 같은 단어를 같은 의미로 쓰고 있는지 확인하라.
TechnicalCommunity 안에서 용어의 정의를 끊임없이 토론하라.
- 용어 사전(Glossary)을 위키에 정리하는 것도 좋은 방법이다.
Real Examples
Example 1: From Technical to Domain
Before: StatusUpdateService (기술적 관점) After: OrderWorkflow (비즈니스 관점) 이름을 바꾸는 것만으로도 이 클래스가 주문의 흐름을 관리한다는 사실이 명확해진다.
Example 2: Evolving Concepts
초기에는 모든 결제 수단을 Card라고 불렀으나, 현금과 포인트가 추가되면서 이를 PaymentMethod라는 상위 개념으로 통합하고 진화시켰다.
Common Pitfalls
"It's just a name" (이름일 뿐이잖아요)
이름은 개념 그 자체다. 잘못된 이름은 잘못된 사고를 낳는다.
Large-scale Renaming (대규모 이름 변경)
한꺼번에 수천 군데의 이름을 바꾸려다 충돌을 일으키는 것.
AtomicCommit을 사용하여 작게 나누어 진행하라.
Meaning Overload (의미의 과부하)
하나의 단어에 너무 많은 의미를 담으려 하는 것.
- 맥락(Context)에 따라 단어를 분리하라.
Connection to Other Patterns
NamesAsDesign - LivingVocabulary는 NamesAsDesign을 시간 축으로 확장한 것이다. 시간적 확장
LanguageBuilding - 구축된 언어가 썩지 않도록 유지보수하는 활동이다. 유지보수
OrganicGrowth - 시스템이 자랄 때 언어도 함께 자라야 한다. 병행 성장
Refactoring - 이름 변경은 리팩토링의 가장 기본이자 강력한 도구다. 기법
Signs of Success
- 코드를 소리 내어 읽었을 때 비즈니스 시나리오가 자연스럽게 들린다.
- 도메인 전문가가 코드를 보고도 "아, 무슨 뜻인지 알겠네요"라고 말한다.
- 새로운 요구사항이 들어왔을 때, 기존 어휘를 조합하여 쉽게 표현할 수 있다.
- 팀 내 의사소통에서 오해로 인한 버그가 현저히 줄어든다.
The Ultimate Insight
코드는 텍스트가 아니라 사유의 기록이며, 어휘는 그 사유를 담는 그릇이다.
당신의 그릇이 낡고 작아졌다면 주저 없이 깨뜨리고 더 크고 정교한 그릇을 빚어라. 살아있는 어휘는 당신의 코드를 생명력 넘치는 숲으로 만들 것이다. 언어를 다듬는 일에 인색하지 마라. 그것이 시스템의 영혼을 가꾸는 일이다.
CategoryPatternLanguage CategoryProgramming CategoryRefactoring CategoryLanguage CategoryDDD
