코드 설계를 배우는 이유
코드설계를 배우면 확장성과 가독성이 높은 유지보수가 용이한 코드를 작성 가능하다.
코드 설계 지식은 사실 일반적으로 사용되지 않는 판타지스러운 것이 아닌가? (책에서 왜 배워야 하는지 설명)
고품질의 코드 작성
대부분의 개발자는 고품질 코드를 작성할 시간이 없을 뿐 아니라, 무엇이 '고품질 코드' 인지 알지 못해 처음 입사했을 때와 비슷한 수준의 코딩 스킬을 구사한다.
복잡한 코드 개발 다루기
개발하면서 만나는 어려움 두가지가 있다.
① 고도의 기술이 필요한 케이스 - 자율 주행, 비디오 인식 등
② 높은 수준의 기술은 필요하지 않지만, 코드의 양이 많거나 비즈니스 적으로 복잡한 케이스
②번 '소프트웨어 개발의 복잡성' 은 코드 설계 지식으로 해결 가능하다.
*유지보수하기 좋은 코드를 작성하기 위해 생각해 볼 질문들
계층화와 하위 모듈화 방법은 무엇인가?
클래스를 어떻게 나누는 것이 좋은가?
각 클래스에는 어떤 속성과 메서드가 있는가?
클래스 간 상호 작용을 설계하는 방법은 무엇인가?
상속이나 연관을 사용하는 것이 좋은가?
인터페이스나 추상 클래스를 사용하는 것이 좋은가?
결합도가 높은 코드와 낮은 코드는 무엇인가?
디커플링을 달성하는 방법은 무엇인가?
싱글턴 패턴이나 정적 메서드를 사용하는 것이 옳은가?
팩터리 패턴을 사용하는 것이 좋은가?
가독성, 확장성을 위해 디자인패턴을 도입하는 방법은 무엇인가?
프로그래머의 기본 능력
소스 코드를 읽으면서 완벽하게 이해하지 못하는 것은 기본적인 기술적 지식과 소양이 부족하기 때문이다.
오픈소스, 프레임워크, 미들웨어를 읽을 때 작성자의 의도와 설계를 완벽하게 이해하기 위해서는 디자인 패턴과 설계원칙에 대한 지식이 필요하다.
경력 개발에 필요한 기술
주니어 개발 엔지니어 때는 프레임워크, 프로그래밍 언어만 습득하면 개발 업무에 투입될 수 있지만, 수석 엔지니어로 성장하기 위해서는, 기본적 지식을 학습하여 좋은 코드를 작성할 수 있어야 한다.
- 그래야, 주니어 엔지니어의 코드 리뷰, 양성이 가능하다.
- 고품질 코드가 무엇인지 모르는 시니어라면, 어떻게 주니어를 리드할 수 있겠는가?
기술 리더로 성장하기 위해서는 프로젝트의 진행 상황, 효율성, 품질을 신경써야 한다.
- 쓰레기 코드(ㅋㅋㅋㅋ) 를 작성하는 것을 반복하여 프로젝트의 유지보수와 수정을 어렵게 하고 버그 패치 작업을 계속하게 만들면 안된다.
코드 품질 평가 방법
"좋다, 나쁘다 / 잘 작성되었다, 잘 작성되지 않았다" 등의 추상적인 기준 대신에 가독성, 확장성, 높은 응집도 및 낮은 결합도 등의 기준을 사용하는 것이 좋다. 흑백 논리의 평가 보다는 연속적인 값 중으로 평가할 수 있는 지표가 좋다. (0 ~ 100 점 중 몇 점?)
유지 보수성
유지보수가 쉽다는 것은 기존의 코드 설계를 손상시키거나 새로운 버그를 발생시키지 않고도 빠르게 코드를 수정하거나 추가할 수 있다는 의미다. 유지보수가 어렵다는 것은 코드를 수정하면 새로운 버그가 발생할 위험이 크고 기능이 완벽하게 동작하기까지 시간이 필요하다는 것이다. 간결성, 가독성, 확장성, 모듈성, 응집도와 결합도 등이 공통적으로 작용한 결과가 유지 보수성이 된다.
가독성
코드를 읽고 이해하기 쉽게 작성하자.
- 마틴 파울러, "컴퓨터가 이해할 수 있는 코드는 바보라도 작성할 수 있다. 휼륭한 프로그래머는 사람이 이해할 수 있는 코드를 작성한다."
- 구글에는 '가독성 인증' 을 받은 개발자만 코드를 approve 할 수 있다. (ㅇ오??)
### 확인할 것들
코드의 네이밍이 의미가 있는지
주석이 자세히 기술되어 있는지
함수 길이가 적절한지
모듈 구분이 명확한지
코드가 높은 응집도와 늦은 결합도를 가지는지
코드 리뷰를 받았을 때 작성한 코드에 대한 많은 질문을 받는다면 코드의 가독성에 문제가 있다는 뜻이므로 리뷰를 통해 가독성을 판단해보자.
확장성
새로운 기능을 추가할 수 있는 여지를 초기부터 고려하여 기존 코드를 대량으로 수정하지 않고도 새로운 기능을 추가할 수 있다는 의미이다.
유연성
다음과 같은 경우를 모두 유연성이 높다고 한다.
① 기존 코드가 확장성이 높아 기존 코드를 수정하지 않고 새 기능을 추가할 수 있을 때
② 재사용 가능한 모듈과 클래스 등을 상속받아 간단하게 구현할 수 있을 때
③ 클래스가 다양한 시나리오에 대응할 수 있을 때
간결성
KISS (Keep It Simple, Stupid)
단순하고 명확한 원칙을 지키자.
단순한 코드에 기술적 내용이 없다고 복잡한 디자인패턴을 도입하는 행동을 하지 말자.
재사용성
반복저인 코드 작성을 최소화하고 기존 코드를 재사용하는 것이다.
상속(다형성), 단일 책임 원칙, 디커플링, 모듈화 등으로 코드 재사용성을 높일 수 있다.
DRY(Don't repreat yourself)
테스트 용이성
앞의 여섯가지 기준에 비해 덜 중요하지만, 역시 중요하다.
테스트 용이성이 낮으면 단위 테스트를 작성하기 어렵다는 것이고 코드 설계에 문제가 있음을 보여준다.
고품질 코드를 작성하는 방법
앞의 7가지 고품질 코드 기준을 충족하는 코드를 작성하기 위해 배워야 하는 것들이다.
객체 지향
프로그래밍 패러다임을 주도하는 세 가지 스타일: 절차적 프로그래밍, 함수형 프로그래밍, 객체지향 프로그래밍
객체지향 프로그래밍은 다양한 설계원칙과 디자인 패턴 구현의 기초 개념이 된다.
### 책에서 다루는 객체 지향 관련 내용
캡슐화, 추상화, 상속, 다형성
객체지향 분석, 객체지향 설계, 객체지향 프로그래밍
인터페이스와 추상 클래스의 차이점과 각각의 응용 시나리오
구현이 아닌 인터페이스를 기반으로 한 설계 사상
더 많은 합성, 더 적은 상속의 설계 사상
설계 원칙
설계 원칙은 추상적이고, 정의와 설명이 모호하며, 동일한 설계 원칙에 대해 사람마다 해석이 다르다.
따라서 설계 원칙 정의만 '암기' 한다고 해서 설계 원칙을 완벽하게 마스터할 수 있는 것은 아니고, 어떤 시나리오를 해결하는데 도움이 되는지 파악하고 있어야 한다. 설계원칙은 디자인패턴보다 더 보편적이고 중요하다.
단일 책임 원칙 (Single Responsibility Principle)
개발 페쇄 원칙 (Open-Closed Principle)
리스코프 치환 원칙(Liskov Substitution Principle)
인터페이스 분리 원칙(Interface Segregation Principle)
의존 역전 원칙(Dependency Inversion Principle)
KISS 원칙 (Keep It Simple Principle)
YAGNI 원칙 (You Aren't Gonna Need It Principle)
DRY 원칙 (Don't Repeat Yourself Principle)
LoD (Law of Demeter)
디자인 패턴
개발에서 자주 접하게 되는 일부 설계 문제에 대해 요약된 솔루션 또는 설계 사상으로, 코드 디커플링과 확장성 문제를 다룬다.
싱글턴 패턴과 같은 일부 디자인 패턴은 더 이상 사용되지 않고, 프로그램 언어에 포함되어 새롭게 등장하는 패턴도 있다.
### 디자인 패턴의 분류
생성 디자인 패턴
- 싱글턴 패턴, 팩터리 패턴, 빌더 패턴, 프로토타입 패턴
구조 디자인 패턴
- 프록시 패턴, 데커레이터 패턴, 어댑터 패턴, 브리지 패턴, 퍼사드 패턴, 복합체 패턴, 플라이웨이트 패턴
행동 디자인 패턴
- 옵서버 패턴, 템플릿 메서드 패턴, 전략 패턴, 책임 연쇄 패턴, 상태 패턴, 반복자 패턴, 비지터 패턴, 메멘토 패턴, 커맨드 패턴, 인터프리터 패턴, 중재자 패턴
코딩 규칙
변수, 클래스, 함수, 코드에 대한 명명 규칙, 코드에 주석을 다는 범위와 같은 코딩 규칙으로 가독성을 향상시킨다.
디자인 패턴, 설계 패턴에 비해 구체적이고 깊게 생각할 필요 없이 규칙을 지키는데 집중하면 되기 때문에 복잡하지 않은 프로그램이라도 해당 사항들은 점검해보는 것이 좋다.
리팩토링
디자인패턴, 설계원칙, 코딩 규칙을 이용하여 코드 품질이 저하되는 것을 방지한다.
### 책에서 다루는 리팩토링 관련 내용
1) 리팩토링의 목적, 대상, 시기, 방법
2) 리팩토링에 오류가 없는지 확인하기 위한 기술적 수단: 단위 테스트, 코드 테스트 용이성
3) 두 가지 다른 규모의 리팩토링: 대규모 고수준의 리팩토링, 소규모 저수준 리팩토링
객체지향 프로그래밍, 설계 원칙, 디자인패턴, 코딩 규칙, 리팩토링 기술을 이용한 코드 품질 개선은 의도적인 훈련과 연습이 필요하다. 코드를 작성하기 전 앞으로 확장 요구 사항, 어느 부분이 변경되고 유지될지, 이렇게 작성하면 다음에 코드를 작성할 때 불편하지는 않을지 등을 의도적으로 의식하고 작성할 필요가 있다.
과도한 설계를 피하는 방법
과도하게 설계에 많은 시간을 투입하고 남용하지 말자.
코드 설계의 원래 의도는 코드 품질을 향상시키는 것이다.
- 코드 설계가 코드의 어떤 품질을 개선할 수 있는지 명확하지 않다면 '설계를 위한 설계'가 될 뿐이다.
코드 설계의 원칙은 앞에 문제가 있고, 뒤에 방안이 있다는 것이다.
- 가독성이 낮고 확장성이 떨어지는 등 코드의 pain point를 먼저 분석하고, 해당 포인트를 개선하기 위한 디자인 패턴과 설계 원칙을 사용해야 한다.
- 먼저 사용하고 싶은 디자인 패턴을 손에 쥐고 문제가 뭐지? 하고 찾아 각종 디자인 패턴을 적용해보는 ... 행동을 하지 말자.
코드 설계의 응용 시나리오는 복잡한 코드에 적용되어야 한다.
- 데이터가 크지 않을 때 알고리즘을 사용하여 개선하는 것이 의미가 없는 것 처럼, 코드가 복잡하지 않다면 복잡한 디자인 패턴을 적용할 필요가 없다.
특정 시나리오 외의 코드 설계에 대해 이야기하지 않는다.
- 코드를 개발하는 특정 맥락(대규모 프로젝트인지, 저수준프로그램인지 등)에 따라 필요한 전략이 다를 수 있으므로 해당 시나리오에 맞는 코드 설계를 선택해보자.
'BE 📙 > 디자인패턴의 아름다움' 카테고리의 다른 글
| [CH 05.01, 05.02] 리팩토링, 단위테스트 (4) | 2025.08.12 |
|---|---|
| [CH03.01] 설계 원칙 - 단일 책임 원칙 (1) | 2025.08.05 |
| [CH02.09] 상속보다 합성 (1) | 2025.08.04 |
| [CH03.07-03.08] 설계원칙 (4) | 2025.07.31 |
댓글