본문으로 건너뛰기

버그 제보

이상한 점을 알려 주시면 고칠게요. 지금 보고 있는 페이지와 브라우저 정보가 함께 담겨요.

페이지:

Tools

Simple Design

작성 2026. 10. 13.추가
목차12개 항목
출처와 참고

박영록의 위키 글 「Simple Design」(2024.06)을 요약·재구성한 노트다. DRY·KISS·YAGNI 비교는 「fru1tworld/cs-basic 모의 면접 질문 목록」을 점검해 보강했다.

왜 객관적 기준이 필요한가

전문가는 직관으로 일해도 좋은 코드를 쓰고, 그러면서도 자기 설계를 계속 의심한다. 초보자는 직관이 부족한데도 "더 깔끔해 보여서", "가독성이 좋아서" 같은 느낌으로 설계한다. 느낌은 사람마다 달라서 팀 안에서 부딪힌다.

표현문제
가독성, 읽기 쉽다/어렵다자기 눈에 안 들어오면 "읽기 어렵다"가 된다. 주관적으로 평가하고 주관적으로 쓰게 만든다
깔끔하다, 지저분하다기준이 없어 개선 방향을 주지 못한다
클린 코드책이 기준을 주지만 모두 동의할 만한 기준은 아니다

이런 표현은 본질적 복잡성(essential complexity)을 우발적 복잡성(accidental complexity)으로 착각하게 만든다는 문제도 있다. 우발적 복잡성은 도구·언어·코드 품질로 줄일 수 있지만, 본질적 복잡성은 풀려는 문제 자체에 있어서 코드로는 줄일 수 없다.

좋은 기준은 다음 조건을 갖춘다.

  • 냄새가 나는지는 모호함 없이 판단할 수 있다. 초보자에게 지침이 된다.
  • 언제, 어떻게 고칠지는 열어 둔다. 전문가를 묶지 않는다.
  • 개수가 적다. 복잡성을 다루는 원칙이 복잡하면 그것도 문제다.

Simple Design의 네 규칙

켄트 벡의 원래 문구와 마틴 파울러의 재해석을 합치면 다음과 같다.

순서규칙실무에서
1모든 테스트를 통과한다당연해서 따로 말할 필요가 없다
2중복이 없다 (평행 상속 구조 같은 숨은 중복 포함)핵심
3의도를 드러낸다가장 주관적이라 초보자에겐 부작용이 있다. 빼도 손해가 적다
4문법 요소가 최소다핵심

1과 3을 빼면 한 줄 정의가 남는다.

중복이 없으면서 최소한의 문법 요소로 구성된 코드

최소한의 문법 요소

켄트 벡은 "클래스와 메서드", 파울러는 "요소"라고 했다. 이를 코드 수준에서 셀 수 있게 좁히면 문법 요소가 된다.

  • 클래스, 메서드, 상속 계층, 콜 스택 깊이
  • 멤버 변수, 로컬 변수, 데코레이터
  • if 분기, 루프. 순환 복잡도(Cyclomatic Complexity)가 느는 것도 문법 요소가 느는 것이다
  • 여기에 전체 코드 분량(TLoC)까지 줄이면 더 좋다

중복을 없애면 문법 요소는 어느 정도 늘 수밖에 없다. 기준은 같은 중복을 더 적은 요소로 없애는 쪽이다. 메서드 하나 추출로 끝나는 방법이 클래스나 상속 계층을 추가하는 방법보다 낫다.

DRY, KISS, YAGNI

코드 품질 원칙으로 자주 묶어 부르는 세 약어는 Simple Design의 규칙과 겹친다.

원칙뜻Simple Design과의 관계지나치면
DRY(Don't Repeat Yourself)시스템 안의 모든 지식은 단 하나의 명확하고 권위 있는 표현을 가져야 한다. 『실용주의 프로그래머』에서 나왔다. 대상은 같은 글자의 코드가 아니라 같은 지식(규칙, 계산식, 상수, 스키마)이다「중복이 없다」우연히 모양만 같은 코드를 억지로 합쳐 서로 다른 이유로 바뀌는 코드를 묶는다
KISS(Keep It Simple, Stupid)같은 문제를 푸는 방법 중 가장 단순한 것을 고른다. 복잡도는 필요가 증명될 때만 더한다「문법 요소가 최소다」단순함을 핑계로 필요한 추상화나 오류 처리를 빼서, 중복이 쌓인다
YAGNI(You Aren't Gonna Need It)지금 필요하지 않은 기능·확장 지점·설정은 만들지 않는다. 익스트림 프로그래밍(XP)에서 나왔다현재 요구에 충실한 설계이미 알고 있는 요구까지 미뤄, 곧 다시 뜯어고친다

셋은 서로를 견제한다. DRY만 밀면 추상화가 늘어 KISS와 부딪치고, 그 추상화가 미래 대비라면 YAGNI에 어긋난다. Simple Design은 이 충돌을 「같은 중복을 더 적은 요소로 없앤다」는 한 기준으로 정리한다. 시스템 설계 차원의 KISS는 시스템 설계의 품질 속성과 트레이드오프의 약어 표에도 있다.

중복은 언제 없애나

"미래에 갈라질 수 있으니 남겨 둔다"는 YAGNI 위반이다

「Don't DRY Your Code Prematurely」 류의 주장은 "지금은 같아도 나중에 로직이 달라질 수 있다"를 근거로 든다. Simple Design 관점에서는 이것이 오히려 YAGNI에 어긋난다. 아직 오지 않은 변화를 근거로 설계하는 것이기 때문이다. 좋은 코드는 현재에 충실한 Simple Design이지 미래 변화에 대비한 유연함이 아니다.

def assert_future(deadline):
    if deadline <= datetime.now():
        raise ValueError('blah')
    return deadline
 
set_task_deadline(assert_future(datetime(2024, 3, 12)))

중복을 없애더라도 함수 하나로 끝내는 식으로 문법 요소를 최소화한다.

남겨 둘 이유는 비용뿐이다: 밥 먹기 전에 설거지하기

다시 만질 일이 없거나 영향 범위가 좁은 코드는 고쳐도 이득이 없다. 그래서 중복이 실제로 해를 끼치기 시작할 때 없앤다. 설거지의 이득은 다음 끼니에야 생기니, 다음 끼니 직전에 하는 것과 같다.

이 판단은 작은 단위로 한다.

flowchart LR
  A["A"] --> B["B"] --> C["C"] --> D["D<br/>(최종 결과, 다른 곳에서 안 씀)"]
  B --> D
  • A, B, C: 다른 모듈이 기대므로 다 만들면 바로 리팩터링
  • D: 의존하는 곳이 없으니 일단 둔다 → 연결이 생길 때 리팩터링

초보자라면 가끔은 극단적으로

비용 저울질은 개선 비용을 가늠할 수 있어야 가능하다. 그래서 초보자에게는 중복을 하나도 남기지 않는 극단적인 품질 추구를 권한다.

  • 유지보수 단계의 회사가 스타트업보다 많다. 스타트업도 몇 달 만에 "갈아엎자"는 말이 나오거나, 핵심 기능 하나 넣다가 버그가 쏟아지는 일이 흔하다.
  • 극단까지 밀어 보면 여러 방법을 탐색하게 되고 그 과정에서 배운다.
  • 비용과 타협하는 리팩터링은 스스로 코드 품질 전문가가 됐다고 느낄 때 시작해도 늦지 않다.

코드 품질은 속도를 위한 것이다

  • 품질을 높이는 이유는 더 빨리 개발하기 위해서다. 품질 때문에 일정이 늘어난다면 품질을 잘못 이해한 것이다.
  • 품질을 희생해 빨라지는 건 맥락이 머릿속에 다 들어 있을 때뿐이다. 보통 30분, 길어야 몇 시간 분량이다. 그보다 큰 일에서는 자기가 쓴 나쁜 코드를 다시 읽으며 손해를 보기 시작한다.
  • 어떤 냄새는 하루 이틀짜리 작업도 늦춘다. 어떤 중복이 해롭고 어떤 중복이 무해한지 가리는 것이 곧 실력이다.
  • 방법론은 성과를 보장하지 않고 확률을 높인다. 과학적 방법론이 과학적 성과를 보장하지 않아도 과학자는 그것을 쓴다. 품질이 좋다고 성공하진 않지만, 품질이 나빠 기능 추가에 실패하고 정체되는 회사는 많다.

더 구체적인 기준이 필요할 때: 나쁜 냄새

Simple Design만으로 부족하면 『리팩터링』의 나쁜 냄새(code smell) 목록을 찾아본다. 머릿속에 다 담고 다니기엔 많지만, 냄새를 맡았을 때 "이건 무슨 냄새고 어떻게 고치나"를 찾아보고 설명하는 데는 아주 좋다.

본질적 복잡성에도 도전한다

본질적 복잡성 때문에 코드가 복잡하다면 코드 대신 비즈니스 규칙을 건드린다. 개발자가 이해하기 어려운 규칙이면 운영 실무자도 이미 힘들어하고 있다.

단계환불 규칙 사례
첫 미팅8개 정도로 정리됨
개발 중담당자도 몰랐던 규칙이 계속 나와 30개까지 늘어남
뜯어보니월 수백~수천 원 손해면 되거나 아무도 손해 보지 않는 규칙이 많음
협의 후10여 개로 줄임

요구사항은 담당자마다 다른 생각에서 나와 끝없이 불어난다. 규칙 전체를 보는 개발자가 함께 다듬으면 비즈니스 비용도 준다. 냄새의 원인이 본질적이든 우발적이든, 맡았으면 고쳐 본다.

정리

  • "가독성"·"깔끔함" 같은 느낌 대신 판단 가능한 기준으로 이야기한다.
  • 기준은 한 줄: 중복이 없고, 문법 요소가 최소인 코드. 숨은 중복도 찾는다.
  • DRY는 지식의 중복을, KISS는 불필요한 복잡도를, YAGNI는 오지 않은 요구를 경계한다. 셋이 부딪치면 더 적은 요소로 중복을 없애는 쪽을 고른다.
  • 미래 변화를 근거로 중복을 남기지 않는다. 남긴다면 이유는 비용이고, 해를 끼치기 시작할 때 없앤다.
  • 품질은 속도를 위한 수단이다. 부족하면 나쁜 냄새 목록을, 코드로 안 되면 비즈니스 규칙을 본다.

관련 노트: 리팩터링 원칙, 코드 리뷰 원칙과 체크리스트, 프론트엔드에서의 TDD, 삭제하기 쉬운 코드, 시스템 설계의 품질 속성과 트레이드오프

원본 기록2

댓글

GitHub 계정으로 댓글을 남길 수 있어요.