포스트

Simple Design

Simple Design

기반 강의: 인프런 Simple Design 강좌

Simple Design 이란?

Simple Design은 최소한의 구성요소로 중복 없는 코드를 작성하는 설계 철학입니다. 복잡함을 줄여 더 빠른 개발유지보수성 향상을 목표로 합니다.


좋은 코드의 기준

1. 테스트 통과

  • 자동화된 테스트를 만드는 팀에게는 당연한 요건
  • 코드의 동작을 보장하는 기본 조건

2. 의도를 드러내는 코드

  • 중요한 원칙이지만 주관성이 강함
  • 읽는 사람이 코드의 목적을 쉽게 이해할 수 있어야 함

3. 중복이 없으면서 구성요소가 최소한인 코드 [핵심]

  • Simple Design의 핵심 원칙
  • 불필요한 복잡성을 제거한 깔끔한 구조

좋은 코드 작성 방법

핵심 두 단계

  1. 코드에서 중복을 제거한다
  2. 구성요소를 줄일 방법을 찾는다

중복 제거의 어려움과 함정

Extract Method의 위험성

잘못된 Extract Method의 문제점:

  • 코드를 읽기 위해 여러 함수를 뒤적거려야 하는 불편함
  • 차라리 Long Method가 나을 수도 있음
  • Goto Considered Harmful → 함수 사용 증가 → 코드는 순서대로 읽어야 하는데 실행은 점프

언제 함수를 만들어야 할까?

피해야 할 함수

  • Side Effect가 있는 함수
  • 재사용이 필요없는 긴 함수를 단순히 길이 때문에 추출한 경우
  • 멱등성이 보장되지 않는 함수

좋은 함수

  • 순수함수 (Pure Function): 부작용 없음, 들어가볼 필요 없음
  • 중복 제거를 위해 추출한 함수: 대체로 좋은 방법

함수의 두 가지 유형

  • Mutator: 객체의 상태를 변경
  • Accessor: 순수함수, 상태 변경 없음

알아차리기 어려운 중복들

1. 조건문 중복

1
2
3
4
5
6
7
8
// 나쁜 예: 멤버십 조건이 여러 곳에 산재
if (user.getMembershipLevel().equals("GOLD")) {
    // 골드 회원 로직
}
// 다른 곳에서도...
if (user.getMembershipLevel().equals("GOLD")) {
    // 또 다른 골드 회원 로직
}

문제점:

  • IF 조건의 중복은 확산되는 경향 (Shotgun Surgery)
  • 멤버십 케이스가 늘어날 때마다 분기 로직이 중복됨

해결책:

  • 다형성(Polymorphism) 활용

2. 반복 작성해야 하는 코드

  • Getter/Setter 등 보일러플레이트 코드
  • 클라이언트-서버 간 DTO 객체 중복 정의

해결책:

  • 프레임워크 레벨에서 자동 생성
  • OpenAPI 스키마 활용으로 양쪽 코드 생성

구성요소 줄이기

구성요소란?

생각이 필요한 모든 요소들:

  • 클래스, 메서드, 함수, 변수
  • 분기문, 상속 계층
  • 디렉토리, 패키지 구조

구성요소 줄이기를 방해하는 요인

과도한 일관성의 함정

1
2
3
4
5
6
7
나쁜 예시:
/controller/user/
/controller/product/
/controller/order/
/service/user/
/service/product/
/service/order/

문제점:

  • 디렉토리/패키지 레벨을 억지로 맞추려는 욕구
  • 파일 수, 경로 증가로 작업량 늘어남
  • “누구를 위한 일관성인가?” 질문 필요

해결 원칙

“Make the easy things easy, and the hard things possible”

쉬운 일은 쉽게, 어려운 일은 가능하게 하자

일관성의 우선순위

중요한 일관성

  • 깨지면 구체적이고 실제적인 문제 발생
  • 중복을 잘 제거하면 자연스럽게 달성

중요하지 않은 일관성

  • 깨져도 실질적 문제 없음
  • 억지로 맞추려 하지 말 것

Simple Design 실천 가이드

흔한 오해들

“코드 품질을 높이려면 시간이 더 많이 필요하다”

진실: 코드 품질을 높여야 더 빨리 프로젝트를 완료할 수 있다

“리팩토링할 시간이 없다”

진실: 리팩토링을 안해서 시간이 없는 것이다

개발 접근법

“처음부터 완벽하게 하자”는 잘못된 접근

문제점:

  • 처음부터 완벽할 수는 없음
  • 고객 요건은 시간이 지나면서 변경됨
  • 기술적 해답도 변화함
  • 개발자의 도메인 이해도도 성장함

올바른 접근: “점진적 개선”

  • 지속적인 리팩토링
  • 변화하는 요구사항에 유연하게 대응

자동화에 대한 올바른 관점

자동화의 함정

  • 복잡한 것을 자동화하면 복잡함이 고착화
  • 복잡함을 변경하기 어려워짐

도요타의 원칙

“먼저 단순화하고, 그 다음에 자동화하라”

고려사항:

  • 1년에 한두 번 있는 번거로움을 위한 자동화가 정말 필요한가?
  • 자동화 후에는 공정 변경이 어려워짐

Simple Design 적용 수준

드라이퍼스 모델 (Dreyfus Model)

초보자 (Novice)

  • 규칙으로 일한다
  • 극단적으로 Simple Design 추구 권장
  • 경험 부족을 규칙으로 보완

전문가 (Expert)

  • 직관으로 일한다
  • 상황에 따라 유연하게 적용
  • 때로는 중복을 허용하기도 함

실천 가이드라인

초보자라면

  • Simple Design 원칙을 엄격하게 적용
  • 중복 제거에 과도할 정도로 집중
  • 구성요소 최소화를 의식적으로 연습

숙련자라면

  • 상황에 맞는 균형감 있는 판단
  • 때로는 의도적인 중복 허용
  • 비즈니스 가치기술적 완성도 사이의 트레이드오프 고려

후기

모던 소프트웨어 엔지니어링, philosophy of software design 등등의 책에서 말하는 좋은 코드를 작성해야 하는 이유는 모두 동일합니다. 품질이 좋은 코드는 개발 스피드를 올려주고, 개발 스피드로 다시 리팩토링할 여유를 갖고 품질을 유지하기에 선순환이 생긴다는 것입니다.
그럼 무엇이 좋은 코드인가? 에 대해서 의문을 갖고 있던 차에 이 강의를 통해서 좀 더 직관적으로 지켜야 할 원칙에 대해서 공감할 수 있었습니다. 레거시 코드를 보다보면 하나의 로직을 파악하기 위해서 여러 개의 파일, 여러 개의 메서드를 보게되고, 결국 답답함에 시퀀스 다이어그램을 그리고나서야 로직을 파악하게 되는 경우도 많았습니다.
이런 경험을 해보면 꼭 함수를 잘게 쪼개는 것이 코드 품질을 말해주지 않는다는 것을 깨달았고, 제 나름의 유일한 원칙은 ‘테스트 하기 쉬운’ 코드인가 뿐이었습니다. 어떤 로직을 슬라이스 테스트하기 위해서 준비가 복잡할 수록 코드 품질도 좋지 않다는 직관적인 경험이 있었기 때문입니다.
이 강의에서는 좀 더 실전적인 예를 바탕으로 좋은 코드의 기준이 무엇인지를 설명해주고, 어쩌면 당연하게 생각하고 의문을 갖지 않은채 행했던 구조화를 위한 구조화 같은 행위들에 대해서 다시 생각하게끔 해줬습니다. 품질 좋은 코드를 작성하기 위해서 실천할 수 있는 명확한 행동원리에 대해서 다시 생각해볼 수 있는 좋은 강의였습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.