들어가며
“좋은 이름을 짓는 것을 고안하는 시간은 상대적이긴 하지만 공이 많이 든다. 억지로 이름을 붙이지 말아라.”
프로그래밍에서 가장 어려운 것 중 하나가 바로 **이름 짓기(Naming)**입니다. 변수, 함수, 클래스, 모듈… 우리는 매일 수많은 이름을 만들어냅니다.
좋은 이름은 코드를 이해하기 쉽게 만들고, 나쁜 이름은 혼란을 야기합니다. 이 글에서는 그린랩스의 “프로그래머를 위한 이름 짓는 원리”를 바탕으로 체계적인 이름 짓기 방법을 알아보겠습니다.
바람직한 이름의 기준
핵심 원칙
“함수의 내부 코드를 보는 행위를 진행하는 단계까지 오면 바람직한 이름을 갖지 못한 함수다”
이상적인 함수는 이름만 보고도 무엇을 하는지 알 수 있어야 합니다. 내부 구현을 들여다봐야 한다면, 그 이름은 실패한 것입니다.
두 가지 핵심 요구사항
-
함수의 목적을 가리키는 이름 짓기
- 무엇을 하는지가 명확해야 함
- 구현이 아닌 목적에 초점
-
문맥에서 충분히 구체적이면서 간결한 이름
- 너무 일반적이지 않게
- 너무 구체적이지 않게
- 핵심을 정확히 표현
간접화(Indirection): 추상화의 좁은 의미
간접화란?
간접화는 **무엇(인터페이스, 가리키는 방법)**과 **어떻게(실제 구현, 구현체)**를 분리하는 것입니다.
추상화의 좁은 의미를 나타내며, 이를 통해 코드의 계층을 만들어낼 수 있습니다.
왜 간접화가 중요한가?
한 단어가 가진 의미가 넓으면 문맥에서 뜻을 파악할 때 더 많은 노력이 듭니다.
나쁜 예시:
function process(data) {
// 무엇을 처리하는가? 어떻게 처리하는가?
// 이름만으로는 알 수 없음
}좋은 예시:
function validateUserInput(data) {
// 사용자 입력을 검증한다는 목적이 명확
return isValidEmail(data.email) && isValidPassword(data.password);
}간접화 계층의 효과
- 함수가 어떤 데이터를 대상으로 동작하는지 이해하기 쉬워진다
- 구현이 아닌 목적을 기준으로 이름을 붙이면 이름은 간접화를 형성하는 수단이 된다
- 간접화를 통해 양파처럼 계층을 쌓으면서 작업을 하면, 누구라도 이해하기 쉬운 코드가 된다
주의사항
허나 하위 계층까지 간 코드를 보면 의미가 넓어져서 심층적인 코드 파악이 힘들 수도 있다. 레벨을 많이 쌓지 말자.
과도한 추상화는 오히려 코드를 이해하기 어렵게 만듭니다.
이름 짓는 구체적인 방법
1. 간접화 계층을 통해 키워드 바운더리(의미망) 고려
코드가 어느 추상화 레벨에 있는지 파악하고, 그에 맞는 용어를 선택하세요.
2. 이름의 목적(계약)과 수단(구현)을 분리
예시: “은하 데이터에서 목성의 위성을 꺼내와라”
나쁜 이름:
function get목성의위성은하칼리스토() {
// 너무 구체적이고, 구현 세부사항이 포함됨
}좋은 이름:
function getJupiterMoonFromGalaxy(galaxyData, moonName) {
// 목적이 명확하고, 파라미터로 유연성 확보
}의미망(Semantic Network): 추상의 사다리
추상의 사다리
추상의 사다리는:
- 위로 올라갈수록: 높은 추상 레벨, 일반화
- 아래로 내려갈수록: 낮은 추상 레벨, 구체화
균형의 중요성
-
낮은 레벨의 추상만 사용: 지나치게 잡다해짐
function saveUserDataToPostgreSQLDatabaseTableUsersWithEmailValidation() { // 너무 구체적 } -
높은 추상만 고집: 내용이 허황될 우려
function process() { // 너무 일반적 }
협의성(Narrowing): 핵심에 집중
“추상과 구체 사이에서 ‘어떤 특성에 초점을 맞출지’ 고려”
협의성이란 너무 일반적이지 않고, 너무 구체적이지도 않게 균형을 갖추어, 대상의 핵심 특성에 맞게 의미를 좁히는 것입니다.
좋은 예시:
// 적절한 추상화 레벨
function saveUser(userData) {
return db.users.create(userData);
}
function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function sendWelcomeEmail(user) {
return emailService.send({
to: user.email,
template: 'welcome'
});
}실전 적용 가이드
상위어 vs 하위어
알맞은 층위에서 알맞게 말하는 것이 알맞다.
- 구체화가 필요할 때: 하위어 사용
- 일반화가 필요할 때: 상위어 사용
예시:
// 상위어 (일반적)
function fetchData() { }
// 적절한 협의
function fetchUserProfile() { }
// 하위어 (구체적)
function fetchUserProfileFromRESTAPIEndpoint() { }목적 vs 구현
이름은 목적을 나타내야 하며, 구현을 나타내서는 안 됩니다.
나쁜 예시 (구현에 초점):
function loopThroughArrayAndFilter(arr) {
// 구현 방법이 이름에 드러남
}좋은 예시 (목적에 초점):
function getActiveUsers(users) {
// 무엇을 얻는지가 명확
return users.filter(user => user.isActive);
}이름 짓기의 특징과 효과
긍정적 효과
-
함수가 어떤 데이터를 대상으로 동작하는지 이해하기 쉬워진다
function calculateTotalPrice(cart) { // cart 데이터를 대상으로 한다는 것이 명확 } -
구현이 아닌 목적을 기준으로 이름을 붙이면 간접화를 형성하는 수단이 된다
// 계층 1: 비즈니스 로직 function processOrder(order) { validateOrder(order); calculateTotal(order); saveOrder(order); sendConfirmation(order); } // 계층 2: 세부 구현 function validateOrder(order) { // 구체적인 검증 로직 } -
양파처럼 계층을 쌓으면서 작업하면 누구나 이해하기 쉬운 코드가 된다
주의할 점
“코드에서 낯선 이름을 봤을 때, 코드를 읽는 사람이 알아야 하는 건 그 이름의 목적뿐이다.”
독자는 구현 세부사항까지 알 필요가 없습니다. 이름만으로 충분한 정보를 제공해야 합니다.
실전 체크리스트
좋은 이름을 위한 질문들
-
이 함수/변수의 이름만 보고 무엇을 하는지 알 수 있는가?
- 그렇다 → 좋은 이름
- 아니다 → 이름을 개선할 필요가 있음
-
구현 세부사항이 이름에 포함되어 있는가?
- 그렇다 → 목적에 초점을 맞춘 이름으로 변경
- 아니다 → 좋은 방향
-
이름이 너무 일반적이거나 너무 구체적인가?
- 그렇다 → 협의성을 고려하여 균형 잡힌 이름으로 변경
- 아니다 → 적절한 추상화 레벨
-
문맥에서 이 이름이 충분히 명확한가?
- 그렇다 → 좋은 이름
- 아니다 → 더 구체적인 이름 필요
-
계층이 너무 많지는 않은가?
- 그렇다 → 일부 계층을 합치거나 단순화
- 아니다 → 적절한 추상화
실전 예시
Before & After
Before:
// 나쁜 이름들
function getData() { }
function process(x) { }
function doStuff(data, flag) { }
function handleThing() { }After:
// 개선된 이름들
function fetchUserProfile() { }
function validateEmailFormat(email) { }
function calculateDiscountedPrice(price, discountPercent) { }
function sendPasswordResetEmail() { }도메인별 예시
전자상거래:
// 명확한 도메인 용어 사용
function addItemToCart(item) { }
function applyPromoCode(code) { }
function calculateShippingCost(destination) { }
function processPayment(paymentInfo) { }사용자 관리:
// 일관된 동사 사용
function createUser(userData) { }
function updateUserProfile(userId, updates) { }
function deleteUser(userId) { }
function getUserById(userId) { }결론
좋은 이름 짓기는 기술이자 예술입니다.
핵심 원칙 요약
- 목적에 초점: 구현이 아닌 목적을 이름으로
- 협의성 유지: 너무 일반적이지도, 구체적이지도 않게
- 간접화 활용: 적절한 추상화 계층 만들기
- 문맥 고려: 해당 문맥에서 충분히 명확하게
- 과도한 추상화 지양: 레벨을 너무 많이 쌓지 않기
마지막 조언
억지로 이름을 붙이지 마세요. 좋은 이름을 고안하는 데는 시간이 걸립니다. 그러나 그 시간은 결코 낭비가 아닙니다.
좋은 이름은 코드를 문서화하고, 버그를 줄이며, 팀의 생산성을 높입니다.
함수의 내부 코드를 보지 않고도 이해할 수 있는 이름, 그것이 바로 우리가 추구해야 할 목표입니다.
참고 자료
- 그린랩스 기술 블로그: 프로그래머를 위한 이름 짓는 원리
- Clean Code by Robert C. Martin
- Code Complete by Steve McConnell