//
The Programmer's Brain · 펠리너 헤르만스
넷스케이프의 개발자 필 칼튼(Phil Karlton)은 이런 말을 남겼다.
컴퓨터 과학에는 두 가지 어려운 문제만 있다. 캐시 무효화와 이름 짓기.
명명이 어려운 이유는 단순히 창의적인 단어 선택의 문제가 아니다. 아이슬란드 대학교의 연구에 따르면, 같은 코드 개체에 대해 두 프로그래머가 동일한 이름을 선택한 경우는 전체의 **7%**에 불과했다. 이름은 본질적으로 주관적이고, 그렇기 때문에 팀 내 일관성 유지가 더 중요하다.
1. 코드베이스의 상당 부분이 이름이다. 변수명, 함수명, 클래스명, 파라미터명을 합치면 전체 코드에서 식별자가 차지하는 비율은 생각보다 높다. 읽는 행위의 대부분이 이름을 파악하는 것이다.
2. 코드 리뷰는 이름을 통해 이루어진다. "이 변수 이름이 의미하는 것이 무엇인가"로부터 토론이 시작되고, 팀의 공유 이해가 형성된다.
3. 이름은 가장 비용이 낮은 문서다. 잘 지어진 함수명 하나가 다섯 줄의 주석을 대체한다.
4. 이름은 표식 역할을 한다. parseConfig, validateInput, buildResponse 같은 이름은 읽는 순간 그 코드 블록의 청크를 형성한다.
버틀러(Butler) 등의 연구자들은 경험적으로 나쁜 이름의 특성을 열거했다. 코드 리뷰에서 이름 품질을 평가하는 체크리스트로 활용할 수 있다.
| 안티패턴 | 설명 | 나쁜 예 | 좋은 예 |
|---|---|---|---|
| 지나치게 짧은 이름 | 의미를 전달하지 못함 | d, tmp, x | daysSinceCreation, swapBuffer |
| 지나치게 긴 이름 | 읽기 어려움, STM 부담 | theListOfUsersWhoHaveLoggedInToday | todayActiveUsers |
| 약어 남용 | LTM에 없으면 해독 불가 | usrMgr.calcAuth() | userManager.calculateAuth() |
| 유사한 이름 | 두 개의 청크가 혼동됨 | userData vs userInfo | 역할 차이를 명확히 반영 |
| 숫자 접미사 | 역할 구분 없이 나열 | user1, user2 | sourceUser, targetUser |
camelCase냐 snake_case냐는 오래된 논쟁이다. 흥미로운 사실은 두 스타일 모두 해당 스타일에 익숙한 개발자에게 더 잘 인식된다는 것이다. 카멜 케이스를 주로 쓰는 개발자는 카멜 케이스를 더 빠르게 처리하고, 스네이크 케이스를 처음 다룰 때 일시적으로 인지 효율이 떨어진다.
결론은 단순하다: 어느 쪽이든 팀 내에서 일관성을 유지하라. 일관성 자체가 청킹을 가능하게 하는 조건이다.
이스라엘 컴퓨터과학자 드로르 페이텔슨(Dror Feitelson)은 좋은 이름을 짓기 위한 실용적인 절차를 3단계로 정리했다.
예를 들어, 사용자가 마지막으로 로그인한 날짜를 저장하는 변수를 만든다면:
userLastLoginDate 또는 lastLoginAt이 과정을 명시적으로 거치면 이름 짓기가 즉흥적인 선택이 아닌 의도적인 결정이 된다.
팀 내에서 도메인 용어 사전(Ubiquitous Language)을 만들어 공유하면 "2단계 — 단어 선택"에서 일관성을 확보할 수 있다. "사용자"를 user로 쓸지 member로 쓸지, "주문"을 order로 쓸지 purchase로 쓸지를 명시적으로 합의한 팀은 명명 일관성이 크게 높아진다.
마틴 파울러가 정리한 22가지 코드 스멜(Code Smell)은 단순히 "나쁜 코드"의 목록이 아니다. 각각의 스멜은 읽는 사람의 인지 부하를 높이는 구체적인 방식과 연결된다.
긴 메서드 (Long Method): STM이 한 번에 파악할 수 있는 한계를 초과한다. 스크롤 없이 볼 수 있는 함수가 청킹하기 좋다.
긴 파라미터 목록 (Long Parameter List): 작업 기억 공간에서 동시에 추적해야 할 항목이 늘어난다. 파라미터가 5개를 넘으면 인지 부담이 가파르게 상승한다.
기능 편중 (Feature Envy): 한 클래스의 메서드가 다른 클래스의 데이터를 주로 다루는 경우다. 코드를 읽을 때 두 클래스를 동시에 추적해야 하므로 작업 기억 공간에 부담을 준다.
주석이 필요한 코드 (Comments Required): 코드가 스스로를 설명하지 못하고 주석이 필수인 상태는 외재적 인지 부하의 신호다.
미스터리 넘버 (Magic Number): if (status === 3) 같은 코드는 3이 무엇을 의미하는지 LTM에 없으면 추론이 불가능하다.
코드가 실제로 하는 일과 이름이 암시하는 것 사이에 불일치가 있을 때를 언어적 안티패턴이라고 한다. 이것이 일반 코드 스멜보다 더 위험한 이유는, LTM의 기존 스키마가 잘못된 방향으로 추론을 이끌기 때문이다.
| 안티패턴 | 예 | 문제 |
|---|---|---|
| isXxx인데 bool 반환이 아님 | isUserValid() → 사용자 객체 반환 | is 접두어는 bool을 기대하게 함 |
| getXxx인데 계산이나 부작용 있음 | getTotal() → DB 쿼리 실행 | get은 단순 접근을 기대하게 함 |
| setXxx인데 유효성 검사 예외 발생 | setAge(-1) → throw | set은 단순 저장을 기대하게 함 |
언어적 안티패턴은 코드 리뷰에서 잡기 어렵다. 동작 방식을 살펴보기 전에 이름만 보고 넘어가기 때문이다. 특히 타입 정보만으로는 숨겨진 부작용을 알 수 없는 언어(JavaScript, Python 등)에서 더 주의가 필요하다.
코딩 실력이 높아진다는 것은 단순히 더 많은 알고리즘을 아는 것이 아니다. 특정 패턴을 의식적인 노력 없이 처리하는 자동화(Automaticity) 수준이 높아지는 것이다.
심리학자 앤더슨(Anderson)은 기술 습득을 세 단계로 구분했다.
for 루프를 처음 배울 때는 구문 하나하나를 의식하지만(인지 단계), 수천 번 쓰다 보면 거의 생각 없이 작성한다(자율 단계). 자율 단계에서는 작업 기억 공간이 루프 구문 자체에 묶이지 않고 비즈니스 로직에 집중할 수 있다.
자동화가 된 기술은 작업 기억 공간을 거의 차지하지 않으므로, 더 높은 수준의 문제 해결에 인지 자원을 활용할 수 있다.
자동화는 단순한 반복이 아니라 의도적인 연습을 통해 효율적으로 이루어진다. 음악가나 운동선수가 향상이 필요한 특정 기술에만 집중해서 연습하듯, 개발자도 현재 약점에 집중하는 연습이 효과적이다.
실용적인 의도적 연습의 방법들:
AI 코딩 도우미가 보편화된 지금, 의도적 연습의 가치는 오히려 더 올라갔을 수 있다. AI가 코드를 생성하더라도 그것을 검토하고 수정하는 능력은 LTM에 쌓인 패턴 지식에서 나온다. 자동화가 된 기반 지식이 없으면 AI가 생성한 코드의 품질을 판단하기 어렵다.
3부는 명명, 코드 스멜, 자동화라는 세 주제를 인지과학의 언어로 연결한다. 특히 명명에 대한 분석이 실용적이다. "좋은 이름을 지어야 한다"는 당위가 아니라, 왜 좋은 이름이 인지 부하를 낮추는지를 설명하는 근거를 제공한다.
코드 스멜 역시 "나쁜 코드 습관"이 아니라 "인지 부하를 높이는 패턴"으로 재해석하면 코드 리뷰 피드백에 더 명확한 근거를 붙일 수 있다. "이 함수가 너무 길어요"보다 "이 함수는 STM 용량을 초과하는 변수 추적을 요구합니다"가 더 구체적인 이유가 된다.
자동화에 대한 논의는 이론적으로는 타당하지만, 구체적인 실천 방안이 다소 추상적이다. 의도적 연습의 필요성은 공감하지만, 이를 일상 업무 속에서 어떻게 지속할 것인지에 대한 시스템 설계는 책 밖에서 개인이 해결해야 할 과제로 남는다.
이 글이 도움이 되셨나요?