코드 리뷰를 하다 보면 유난히 자주 마주치는 장면이 있어요.
기능 하나 고치려고 검색했는데, 거의 똑같은 코드가 세 군데서 나오는 겁니다. 하나만 고치면 나머지 두 개는 그대로 버그로 남는 거죠.
오늘의 주인공은 이 문제를 정면으로 겨냥하는 원칙, DRY예요. 지난번에 다뤘던 KISS 원칙과 짝꿍처럼 붙어 다니는 녀석입니다.
DRY는 “Don’t Repeat Yourself”의 약자입니다. 같은 지식을 시스템 안에서 반복하지 말라는 원칙이에요.
1999년에 나온 책 <실용주의 프로그래머>에서 앤디 헌트와 데이브 토머스가 정리한 개념인데, 원문 정의가 꽤 정확합니다.
모든 지식은 시스템 안에서 단 하나의, 모호하지 않은, 권위 있는 표현을 가져야 한다.
여기서 눈여겨볼 단어는 ’코드’가 아니라 ’지식’이에요. 이게 오늘 이야기의 핵심입니다.
코드 복붙이 왜 문제일까?
복사-붙여넣기 자체가 죄는 아니에요. 문제는 그 다음에 벌어집니다.
같은 로직이 세 군데 있으면, 요구사항이 바뀔 때 세 군데를 전부 찾아서 고쳐야 해요. 하나라도 놓치면 그게 버그가 됩니다.
// 배송비 계산이 세 파일에 흩어져 있다면
// Cart.swift
let fee = total >= 50000 ? 0 : 3000
// Checkout.swift
let shippingFee = totalPrice >= 50000 ? 0 : 3000
// OrderSummary.swift
let delivery = price >= 50000 ? 0 : 3000
어느 날 “무료배송 기준을 3만 원으로 내리자”는 요구가 들어오면? 세 파일을 전부 찾아야 합니다. 검색어도 제각각이라 하나쯤은 꼭 놓치고요.
// 지식을 한 곳에 모으면
// Shipping.swift
enum ShippingPolicy {
static let freeShippingThreshold = 50000
static let fee = 3000
static func shippingFee(for total: Int) -> Int {
total >= freeShippingThreshold ? 0 : fee
}
}
이제 정책이 바뀌면 딱 한 곳만 고치면 됩니다. 이게 DRY예요.
코드가 아니라 ’지식’의 중복입니다
그런데 여기서 많은 분들이 한 번 삐끗합니다. DRY를 “비슷하게 생긴 코드를 전부 합쳐라”로 읽는 거예요.
DRY가 말하는 중복은 코드 모양이 아니라 지식, 그러니까 비즈니스 규칙의 중복입니다.
이 구분이 왜 중요하냐면, 세상에는 우연히 닮은 코드가 있거든요.
| 상황 | 중복일까? |
|---|---|
| 배송비 계산 로직이 세 군데 | 진짜 중복 (같은 지식) |
| 회원가입 검증과 이벤트 응모 검증이 우연히 비슷 | 가짜 중복 (다른 지식) |
| 상수 3000이 배송비와 포인트 적립 기준에 각각 등장 | 가짜 중복 (다른 의미) |
회원가입 검증과 이벤트 응모 검증이 지금은 둘 다 “이름 필수, 전화번호 11자리”라서 코드가 똑같아 보여도, 두 규칙은 서로 다른 이유로 바뀝니다. 이걸 하나로 합쳐두면 이벤트 규칙 바꾸다가 회원가입이 터져요.
섣부른 추상화가 중복보다 비쌉니다
그래서 요즘 커뮤니티에서는 이런 말도 자주 나옵니다. “잘못된 추상화보다는 중복이 낫다(prefer duplication over the wrong abstraction)“고요. 샌디 메츠라는 유명한 루비 개발자가 한 말이에요.
비슷해 보이는 코드 두 개를 억지로 합치면 이런 일이 벌어집니다.
- 공통 함수를 만든다
- 한쪽 요구사항이 바뀌어서 옵션 파라미터를 추가한다
- 다른 쪽도 바뀌어서 if 분기를 추가한다
- 어느새 파라미터 5개짜리 아무도 이해 못 하는 함수가 된다
이쯤 되면 차라리 복붙 두 벌이 나았던 겁니다.
그래서 실무에서는 ’3의 법칙(Rule of Three)’을 많이 써요. 같은 패턴이 두 번 나오면 일단 참고, 세 번째 나왔을 때 추상화하는 겁니다. 세 번쯤 반복되면 그게 진짜 같은 지식인지 우연인지 보이거든요.
제가 쓰는 판단 기준
저는 중복을 발견하면 이 질문 하나를 던집니다.
이 두 코드는 같은 이유로 바뀌는가?
같은 이유로 바뀐다면 진짜 중복이니 합칩니다. 다른 이유로 바뀐다면 생긴 게 아무리 닮았어도 그냥 둡니다.
오늘의 결론
DRY 원칙, 핵심만 추리면 이렇습니다.
- 중복의 단위는 코드 모양이 아니라 지식(비즈니스 규칙)입니다.
- 같은 이유로 바뀌는 코드만 합치세요. 우연히 닮은 코드는 그대로 두세요.
- 확신이 없으면 3의 법칙. 세 번째 반복 때 추상화해도 늦지 않습니다.
KISS가 “단순하게 유지해라”라면, DRY는 “지식을 한 곳에만 둬라”입니다. 둘 다 결국 변경 비용을 줄이자는 얘기예요.
검색 한 번에 세 군데씩 걸리는 로직, 하나쯤 떠오르실 텐데요. 그게 오늘의 리팩토링 후보입니다.
