소프트웨어 3대 원칙(DRY · KISS · YAGNI)
중복 제거(DRY), 단순성(KISS), 필요하지 않으면 만들지 말라(YAGNI). 실무 예시와 안티패턴, 체크리스트까지.
소프트웨어 3대 원칙(DRY · KISS · YAGNI)
요약
- DRY (Don’t Repeat Yourself) — 중복을 제거하라. 같은 지식(비즈니스 규칙, 로직, 상수 등)이 여러 곳에 퍼지지 않게 하라.
- KISS (Keep It Simple, Stupid) — 단순하게 설계하라. 불필요한 복잡성은 피하라.
- YAGNI (You Aren’t Gonna Need It) — 필요하지 않은 기능은 미리 만들지 마라. “혹시 쓰일까”는 대부분 시간 낭비다.
1) DRY — Don’t Repeat Yourself (중복 금지)
핵심
같은 정보를 여러 곳에 두지 말자. 변경 지점이 하나여야 유지보수가 쉽다.
예시 (안티패턴)
1
2
3
4
5
6
7
// 중복된 처리: 수정 시 모든 곳을 바꿔야 함
function priceWithTaxA(price) {
return price + price * 0.1;
}
function priceWithTaxB(price) {
return price + price * 0.1;
}
개선
1
2
3
4
const TAX_RATE = 0.1;
function priceWithTax(price) {
return price + price * TAX_RATE;
}
주의할 점
- 너무 작은 중복까지 무조건 합치면 오히려 추상화가 과해짐. 의미적으로 같은 중복인지(의도와 규칙이 동일한지)를 판단하자.
- 공통 모듈을 만들 때 결합도가 높아지지 않도록 신경쓰기.
2) KISS — Keep It Simple, Stupid (단순하게)
핵심
설계와 코드에서 불필요한 복잡성을 제거하자. 단순한 것이 버그가 적고 이해하기 쉽다.
예시 (안티패턴)
- 복잡한 한 함수가 여러 역할(입력 검증, 비즈니스 로직, DB처리)을 모두 수행하는 경우
- 지나치게 일반화된 추상화로 인해 오히려 사용이 어려워진 API
개선 원칙
- 함수는 한 가지 일만 하게 설계(FSR — single responsibility).
- 명확한 이름과 작은 함수.
- 복잡한 로직은 단계별로 나누고 주석으로 의도 설명.
실무 팁
- 리팩터링 후 테스트를 작성해 단순화가 기능을 깨지 않았는지 확인하라.
- 코드 리뷰에서 “이걸 더 간단히 못하나?”라는 질문을 자주 던져라.
3) YAGNI — You Aren’t Gonna Need It (미래는 미리 만들지 마라)
핵심
미래에 필요할 것 같다는 이유만으로 기능을 미리 만들지 마라. 실제 요구가 생겼을 때 그때 구현하는 것이 비용 대비 효율적이다.
예시 (안티패턴)
- “나중에 멀티테넌시가 필요할지도 모르니”라며 지금부터 모든 코드에 테넌트 추상화 적용
- 미리 만든 복잡한 설정 파서나 플러그인 시스템 (실제로는 단일 설정으로 충분)
개선
- 실제 요구(요청 수, 클라이언트 요청 등)가 확인되기 전까지 단순하게 유지.
- 확장 포인트는 남기되(확장 가능하게), 구체적 구현은 요구가 왔을 때 추가.
주의
- YAGNI를 남용하면 반복적으로 비슷한 코드가 여러 곳에 생길 수 있음 → DRY와 균형 필요.
- 도메인 규칙이 불변으로 보이면 미리 정리해 둘 필요가 있다(예: 결제 규칙).
실무에서 세 원칙의 균형 잡기
이 세 원칙은 서로 보완적이지만 때론 충돌하기도 합니다.
DRY vs YAGNI: 중복 제거를 위해 추상화하면, 그 추상화가 ‘미래 요구’를 위한 과잉설계가 될 수 있다. → 기준: 추상화는 현재의 여러 중복 지점을 해결할 때만 도입하라. “혹시 나중에”를 위해 추상화하지 마라.
KISS vs DRY: 단순성을 위해 중복을 허용할 수도 있다(특히 아주 작은 스코프일 때). → 기준: 중복이 버그 위험을 높이거나 변경 비용을 키우면 DRY 적용.
체크리스트 (코드 리뷰용)
- 이 변경이 중복을 야기하나? → DRY 적용 고려
- 더 단순하게 만들 수 없나? → KISS 우선
- 지금 당장 필요한가? → YAGNI 적용 가능성 검토
- 테스트가 충분한가? 리팩토링 후 테스트로 보호되는가?
짧은 예시 플로우 (의사결정)
- 새로운 요구가 왔다.
- 기존 코드와 겹치는가? → 겹치면 재사용/공통 함수로 모아라(DRY).
- 추상화할 경우 복잡도가 급증하는가? → 그렇다면 단순하게 먼저 구현(KISS).
- 기능을 예측해서 미리 설계할 필요가 있는가? → 아니면 YAGNI로 보류.
마무리
- DRY, KISS, YAGNI는 서로 보완하면서도 상황에 따라 트레이드오프가 필요합니다.
- 규칙을 경전처럼 맹목적으로 따르기보단 “왜”라는 질문을 던지면서 균형 있게 적용하는 것이 핵심입니다.
This post is licensed under CC BY 4.0 by the author.