DRY 원칙 (Don't Repeat Yourself) - 소프트웨어 복잡성을 줄이는 최소 중복의 미학
⚠️ 이 문서는 "모든 지식은 시스템 내에서 단일하고, 모호하지 않으며, 신뢰할 수 있는 표현을 가져야 한다"는 DRY 원칙의 본질을 분석합니다. 단순히 코드 복사-붙여넣기를 금지하는 수준을 넘어, 비즈니스 로직과 데이터 모델의 일관성을 유지하기 위한 아키텍처적 전략을 심층적으로 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: DRY(Don't Repeat Yourself)는 코드 중복 제거(Deduplication)뿐만 아니라, 특정 지식이나 비즈니스 규칙이 시스템 내에서 '오직 한 곳'에만 존재하게 하여 변경 발생 시 신뢰할 수 있는 단일 지점(SSOT)을 확보하는 원칙이다.
- 가치: 중복된 로직은 수정 시 누락을 유발하여 버그를 만들고 유지보수 비용을 폭증시키므로, DRY는 개발 생산성과 소프트웨어의 신뢰성을 보장하는 가장 기본적인 방어 기제다.
- 경계: 무분별한 DRY는 불필요한 추상화와 강한 결합(Coupling)을 초래하므로, 서로 다른 이유로 변경되는 코드(우연한 중복)를 성급하게 통합하지 않는 'WET(Write Every Twice)' 관점과의 균형이 중요하다.
Ⅰ. 개요 (Context & Background)
소프트웨어 개발 과정에서 동일한 검증 로직, 수식, 혹은 상숫값이 여러 클래스에 흩어져 있는 현상은 흔히 발생합니다. 이러한 상태에서 비즈니스 요구사항이 변경되어 수치를 수정해야 할 때, 개발자가 5곳 중 4곳만 수정하고 1곳을 누락하면 시스템은 예측 불가능한 동작을 하게 됩니다.
- Pain Point: 중복된 지식(Knowledge)은 시스템의 엔트로피를 증가시키며, '하나의 변경이 모든 관련 지점에 전파되지 않는' 동기화 오류를 야기합니다.
- 도입 목적: 시스템의 가독성을 높이고, 변경에 유연하게 대응하며, 기술 부채를 사전에 방지하여 지속 가능한 아키텍처를 구축하기 위함입니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
DRY 원칙은 코드 계층(Syntax), 로직 계층(Logic), 데이터 계층(Schema), 그리고 문서화(Documentation) 전 영역에 걸쳐 적용됩니다.
┌─────────────────────────────────────────────────────────────┐
│ [ DRY Principle Architecture ] │
│ │
│ [ Knowledge Source ] [ Redundant Expression ] │
│ (Logic A) ──────────▶ (Copy A') [Violation!]│
│ │
│ ▼ ▼ │
│ [ Refactoring Path ] [ Unified Interface ] │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Shared Service │ │ Single SSOT │ │
│ │ (Logic A Core) │ ◀──────┤ (Single Source │ │
│ └──────────────────┘ │ of Truth) │ │
│ │ └──────────────────┘ │
│ ┌─────────┴─────────┐ │
│ │ Client 1 │ Client 2 │ <── No more Copy-Paste │
│ └──────────┴──────────┘ │
│ │
│ ※ Key Principle: "Every piece of knowledge must have a │
│ single, unambiguous representation within a system." │
└─────────────────────────────────────────────────────────────┘
1. DRY의 3가지 적용 관점
- 코드 중복 (Syntactic Duplication): 동일한 소스코드 텍스트의 반복. 함수 추출(Extract Method)이나 유틸리티 클래스 활용으로 해결합니다.
- 지식 중복 (Conceptual Duplication): 동일한 비즈니스 규칙이 서로 다른 형태로 표현되는 것. 예를 들어, 할인율 계산 로직이 프론트엔드(JS)와 백엔드(Java)에 각각 구현된 경우입니다. 이는 API 호출이나 공통 라이브러리화를 통해 단일화해야 합니다.
- 데이터 중복 (Data Duplication): DB 정규화(Normalization)를 통해 동일한 데이터를 여러 테이블에 중복 저장하지 않고 참조 관계를 구성하는 것입니다.
Ⅲ. 융합 비교 및 다각도 분석 (Comparison & Synergy)
DRY와 상충하거나 보완 관계에 있는 개념들을 분석합니다.
| 구분 | DRY (Don't Repeat Yourself) | WET (Write Everything Twice / Waste Everyone's Time) |
|---|---|---|
| 핵심 철학 | 중복을 제거하고 추상화하라 | 중복을 허용하고 가독성을 확보하라 |
| 장점 | 유지보수 용이성, 일관성 보장 | 낮은 결합도, 독립적 변경 가능 |
| 단점 | 잘못된 추상화 시 강결합 발생 | 수정 시 누락 발생, 코드 비대화 |
| 적용 시점 | 규칙이 확실하고 재사용성이 높을 때 | 요구사항이 불확실하고 우연히 겹칠 때 |
- YAGNI(You Aren't Gonna Need It)와의 관계: DRY를 위해 너무 일찍 추상화를 시도하면 YAGNI 원칙을 위반할 수 있습니다. "세 번 중복될 때 리팩토링하라"는 Rule of Three가 좋은 실무 지침이 됩니다.
Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)
1. 감리 및 기술사적 관점의 판단
- 품질 측면: 소스코드 정적 분석 도구(SonarQube 등)를 통해 'Duplication %'를 측정하고 5% 이내로 관리할 것을 권고합니다.
- 아키텍처 측면: 도메인 주도 설계(DDD)를 통해 Bounded Context를 명확히 하여, 컨텍스트 간의 중복과 컨텍스트 내부의 DRY를 구분하여 처리해야 합니다.
2. 실무 적용 가이드
- 상수 관리: 매직 넘버(Magic Number)를 제거하고 전역 상숫값으로 관리합니다.
- 데이터베이스: 정규화를 통해 데이터 무결성을 보장하되, 성능을 위해 의도적 중복(반정규화)을 할 경우 별도의 동기화 메커니즘을 감리해야 합니다.
Ⅴ. 기대효과 및 결론 (Future & Standard)
DRY 원칙을 철저히 준수한 시스템은 **변경의 영향도 파악(Impact Analysis)**이 명확해집니다. 특정 로직을 고칠 때 그 로직을 사용하는 모든 곳이 동시에 수정되므로 '사이드 이펙트'가 최소화됩니다.
- 미래 전망: 클라우드 네이티브 환경에서는 공통 로직을 마이크로서비스로 분리(Service Mesh의 사이드카 패턴 등)하여 인프라 수준에서 DRY를 실현하는 방향으로 발전하고 있습니다.
- 결론: DRY는 단순한 타이핑 절약이 아니라, **"시스템의 진실을 한 곳에 두는 것"**입니다.
📌 관련 개념 맵 (Knowledge Graph)
- 리팩토링: 함수 추출, 클래스 추출
- 객체지향: 캡슐화, 다형성
- DB: 정규화 (1NF~BCNF)
- 반대 개념: WET (Write Every Twice), Premature Abstraction
👶 어린이를 위한 3줄 비유 설명
- DRY는 "똑같은 말을 여러 번 하지 마세요"라는 규칙이에요.
- 일기장에 "나는 오늘 사과를 먹었다"를 10번 쓰는 것보다, "사과 먹음 x 10"이라고 한 번만 쓰는 게 고치기도 편하겠죠?
- 나중에 사과가 아니라 포도였다는 걸 알았을 때, 한 곳만 고치면 되니까요!