simple design

2026. 7. 18.

코드 품질은 왜 중요한가?

1. 코드 품질의 기준

1.1 가독성은 해로운 기준이다.

1.2 심플 디자인

Pasted image 20260718174952

켄트 벡 설계 원칙에서 제시한 4가지에서 생각해보면

  1. 테스트 통과 - 기본 전제
  2. 드러난 의도 - 주관적, 평가하기에 난이도가 높음
  3. 중복 없음 - 평가 가능
  4. 구성 요소 최소화 - 평가 가능

그래서 심플 디자인에선 중복 없음 / 구성 요소 최소화를 메인으로, 실천적인 원칙으로 다룸.

me; 사실, 의도를 잘 살리고, 잘 드러나는게 꽤 중요하다고 느낀다. 다른 요소들도 최대한 객관적으로 논의할 수 있는 요소들로 추렸지만, 이 점에서 여전히 좋은 코드란 주관적일 수 밖에 없고, 체화해야하는 영역으로 느껴짐.

2. 중복을 제거하라

2.4 - 조건문의 중복

설정값의 분기

me; 우리쪽 코드에서 잘 못하고 있는 점이라 기록

if (process.env.NODE_ENV === "development") {
	console.log("Debug information:", value);
}

환경에 따라 달라지는 게 무엇인지가 프로젝트 전체 코드에 퍼져있어서 한눈에 확인하기 어려워서 종종 실수를 유발한다.

조건문 대신 예외 던지기

코드 품질이 나빠지는 이유 중 예외 상황을 처리하는 코드가 차지하는 비중이 상당히 크다. 예외를 던진 다음에 사용자 인터페이스에 가까운 곳에서 처리하면 호출 스택 중간에 있는 함수들은 예외 상황에 대해 전혀 신경 쓰지 않아도 된다. 하나의 함수는 하나의 일만 해야 한다는 원칙을 지키기도 쉬워진다.

문서와 코드의 중복

실천적인 지침(참고)

  1. 소스코드가 SSOT
  2. 가능한 코드로 전달
  3. 가능하면 자동으로 생성

me;

3. 구성요소를 최소화

같은 가치를 만들어 낼 수 있다면 굳이 많은 비용을 들여야할 필요가 없다.

me; 매우 동의, feature creep을 경계해야한다.

  • 원인: 모든 고객의 요구를 맞추려는 욕심, 명확한 제품 비전 부족, 그리고 시장 점유율을 높이기 위한 경쟁 압력 등
  • 결과: 핵심 가치가 흐려지고, 학습 곡선이 가팔라지며, 리소스 낭비로 이어집니다.
  • 우리로 치면 기획전

3.3 상태

상태의 크기 = 내 작업 기억 영역의 크기

3.3.3 - 반복문 변수 다루기

3.7 테스트 케이스

테스트 커버리지는 유지하면서 테스트 케이스의 수를 줄이자 커버리지가 겹치는 테스트를 양산하지 말라는 뜻 TDD에서도 나쁜 테스트의 증상으로 이야기하는 것

테스트 케이스는 명세의 역할을 하기도 한다. 잘 작성된 테스트 케이스는 그 자체로 좋은 문서가 될 수 있다.

me; tdd를 좀 더 공부해야한다..

4. 좋은 함수 만들기

Learned

  1. 함수는 25줄 안팎이 좋다.
  2. 너무 작은 함수도 경계
    1. 하나의 기능만 하는 함수는 주관적일 수 있지만, public하게 공개할 수 있는, 적당한 what의 크기를 가진 수준이 필요함.
    2. 테스트 케이스를 만들 가치가 없다고 느끼면 함수가 너무 작은 것

4.2 지역 변수를 줄여라

스크롤이 발생하지 않을 정도로 함수의 길이를 통제하는 것이 중요하다.

라인 수가 늘어나면 순환 복잡도, 홀스테드 복잡도 등 코드 복잡성을 측정하는 지표들도 나빠진다는 연구 결과로 참고할 만하다.

me; 오.. 뭔가 컴포넌트를 설계할 때나, 코드 리뷰를 할 때나 비슷한 생각을 하는데, ‘사람이 한 입에 이해할 수 있는 크기’에 대해서 정량적으로 표현한게 재밌었다. 25줄..

4.3 함수는 퍼블릭이어야 한다

me; 오..

5. 코드 품질 개선 방법론

5.1 일단 동작하게 하고, 그 다음에 리팩터링

구현하는 일과 리팩터링하는 일을 따로 시키면 두 가지 일을 모두 훨씬 빠른 시간에 좋은 품질로 해낸다. 켄트 벡 - ‘두 개의 모자’라는 은유, 기능을 구현하는 일과 리팩터링하는 일을 엄격하게 나눔

me; 매사에 경계해야하는 일.. ai에게도 주입해놔야겠다.

XP - 복잡하게 생각하지 말고, 완벽하게 동작하는 방법을 찾지 말고 첫 번째로 떠오르는 방법을 시도 - 동작할 법한 가장 간단한 일을 하라, ‘Do The Simplest Thing That Could Possibly Work’ - 안 되면 고치면 된다. - 가차 없이 리팩터링하라 - ‘Refactor Mercilessly’

‘밥 먹기 전에 설거지하기’ 전략

5.5.3 대기 시간 제거

만약 회귀 테스트가 부족하다면 어떻게 해야 할까? 이때도 회귀 테스트가 없는 상황을 위한 방법을 따로 찾기보다는 회귀 테스트를 충분히 채우는 작업을 선행하는 편이 더 낫다.

me; 매우 공감되고, 예전에 이벤트 / 링크 관련 리팩토링에서 테스트를 먼저 작성했던 기억 + 근데 testable하지 않은 구조여서 좀 어려웠던 기억이 있다.

5.5.5 코드 리뷰의 의사결정권

의사결정권 문제도 중요하다. 풀 리퀘스트(Pull Request)를 리뷰할 때 충돌 이 생기고 그 충돌이 해소되지 않는다면 커미터가 결정할 것인가, 리뷰어가 결정할 것인가? 많은 팀이 리뷰어에 결정권을 주는데, 필자는 반대로 커미터에 결정권을 주는 것을 권한다. 커미터가 리뷰어의 리뷰를 받아들여서 생기는 문제든 거절해서 생기는 문제든, 그 코드에 가장 큰 책임감을 느끼는 사람은 커미터이고, 가장 잘 알고 있는 사람도 커미터이기 때문이다.

me; 완벽히 동의하고, 팀 내에 확산할 필요는 있음.

원칙

  1. 커미터는 리뷰어의 리뷰를 거절할 수 있다.
  1. 리뷰어의 판단으로 그 커미터의 거절이 중대한 잘못이라고 본다면 팀 단위로 올려서 논 의한다.
  2. 팀원들이 모여서 논의해도 결론이 나지 않으면 팀 리더가 결정한다.

5.6 본질적 복잡성과 우발적 복잡성

me; 이 파트가 너무 좋았다

  • 본질적 복잡성: 문제 자체, 비즈니스 규칙에 내재된 복잡성
  • 우발적 복잡성: 구현 과정에서 도구, 기술, 코드 구조 때문에 생기는 복잡성

심플 디자인이 다루는 대상 역시 우발적인 복잡성이다. 코드 품질을 높인다고 해서 안 되는 프로젝트를 되게 할 수는 없다. 우리는 엔지니어로서 기술적인 개선을 통해 우발적 복잡성을 줄이기 위해 노력해야 하지만 그 노력이 프로젝트를 성공시키는 것은 아니라는 점을 인식해야 한다.

그러나 엔지니어의 관심사가 우발적 복잡성에서 멈춰야 한다는 뜻은 아니다. 오히려 그 반대라고 할 수 있다. 우리는 기술적인 노력이 아닌, 다른 관 점을 통해서 본질적 복잡성도 다뤄야 한다. 다룬다는 것이 꼭 복잡성을 줄인다는 것을 뜻하지는 않는다. 브룩스는 이에 대해 점진적인 접근법을 제안 한다. 무엇을 만들어야 할지를 판단하기 위해 오랫동안 고민하고 설계하기 보다는 일단 만들어 보는 것이 무엇을 만들어야 할지 판단하는 데 더 도움이 되며, 점진적이고 반복적으로 개선해 가는 과정에서 복잡성을 조금씩 정복 해갈 수 있다는 것이다. me; 눈물 흘림

하지만 이 정도로도 조금 아쉬운 느낌이다. 필자는 엔지니어가 본질적 복잡성을 잘 다루는 것을 넘어서서 복잡성을 줄일 방법도 찾아가길 바란다. 필자는 우발적 복잡성을 다루는 심플 디자인의 원칙들을 본질적 복잡성에도 적 용해보기를 제안한다. 기본적으로 개발하기 복잡한 소프트웨어는 사용자가 사용하기에도 복잡하다.

코드에서뿐 아니라 비즈니스 규칙이나 소프트웨어의 기능에서도 중복을 제거하고 구성요소의 수를 줄이는 관점은 도움이 된다.

me; 눈물 흘림x2

Pasted image 20260718185029

6. 코드 품질과 AI

사용할 수 있는 prompt (이건 test case)

테스트 케이스 하나를 추가로 통과시킬 때마다 리팩터링을 수행 한다. 리팩터링하는 동안은 동작을 변경하지 않고 구조만 개선 한다.

리팩터링은 최근에 작성한 코드와 다음 단계에 건드리게 될 코드 를 살펴보는 것으로 시작한다. 코드를 살펴보고 다음의 단계로 진행한다.

  1. 함수에서 지역 변수를 최소화한다. 특히 한 번만 사용되는 임시 변수는 만들지 말 것. 이로 인해 한 줄이 너무 복잡해진 다고 느끼는 경우는 적절하게 extract method를 하라.
  2. 함수는 항상 public이어야 한다. 문법적으로 private이 없 더라도, private 느낌으로 한 클래스나 한 모듈에서만 사용 되는 것을 전제하는 함수는 public으로 만들기에 적절한 클래스나 모듈로 역할을 재조정해서 옮긴다.
  3. 앞의 작업을 하고 나서 중복 코드가 있는지 확인하고, 중복 코드를 제거한다. 이 때 클래스, 변수, 함수, 패키지, 모듈 등 등의 구성요소가 가장 적은 방법을 선택한다.

Make it work, make it right, make it fast

← 글 목록으로