Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions 15장/공예영.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## **📕 Ch15. JUnit 들여다보기**

저명한 자바 테스트 프레임워크인 JUnit의 코드를 점진적으로 리팩토링하는 과정을 상세히 보여준다. 예제는 자바지만, 클린 코드 관점에서 언어의 차이는 본질이 아니다. 원칙은 프론트엔드에도 적용된다.

### 1. 복잡한 조건문은 의미 있는 함수로 숨기기
세 항이 넘어가는 복잡한 조건문을 별도의 함수로 캡슐화하고, 함수명을 주석처럼 사용할 수 있다.

```js
// Before: 무엇을, 왜 렌더링하는지 한눈에 파악하기 어렵다.
return (
<div>
{user.isLoggedIn && !isLoading && user.hasPermission('editor') && data.isPublished && (
<EditorComponent />
)}
</div>
);

// After: 'isEditable'이라는 이름만으로도 의도가 명확해진다.
const isEditable = () => {
return user.isLoggedIn && !isLoading && user.hasPermission('editor') && data.isPublished;
};

return (
<div>
{isEditable() && <EditorComponent />}
</div>
);
```
isEditable이라는 함수명 자체가 주석의 역할을 수행하며, 복잡한 비즈니스 로직을 JSX의 렌더링 영역으로부터 깔끔하게 분리해준다. 이는 단순히 코드를 짧게 만드는 것을 넘어, 컴포넌트의 핵심 역할인 '무엇을 보여줄 것인가'에만 집중하도록 돕는다. 마치 복잡한 상태 로직을 커스텀 훅(Custom Hook)으로 분리하여 재사용성과 가독성을 높이는 것과 같은 맥락이다.

### 2. 부정문보다는 긍정문이 더 이해하기 수월하다

프론트엔드에서는 isLoading, isError, isValid 같은 플래그를 자주 쓴다. 이때 !isNotValid보다 isValid, !isNotLoading보다 isLoading이 인지 부하가 훨씬 낮다. <br />
예를 들어 if (!isLoading && !isError)는 두 번 부정해석을 거쳐야 하지만, if (isSuccess)는 즉시 이해된다. 상태를 설계할 때부터 긍정형을 기본값으로 두면 버그가 줄고 협업이 수월해진다.


### 3. 시간적인 결합은 외부로 노출하기
책에서 언급된 '시간적인 결합'은 프론트엔드에서도 중요하게 고려해야한다. 데이터 fetching, 렌더링, 애니메이션, 사용자 입력 등 모든 것이 비동기적으로 얽혀 순서가 매우 중요하기 때문이다.

<br />
이때는 props로 결합을 명시할 수도 있고, 래퍼 컴포넌트를 만들어 그 로직의 순서를 명시할 수도 있다.


### 마무리
> "세상에 개선이 불필요한 모듈은 없다. 코드를 처음보다 조금 더 깨끗하게 만드는 책임은 우리 모두에게 있다."

JUnit이라는 거대한 오픈소스 프로젝트의 일부 코드를 리팩토링하는 과정을 천천히 따라가니 나도 오픈소스에 기여하는 기분이라 재밌었다.
<br />
프론트엔드 생태계는 빠르게 변하지만, 가독성, 명확성, 예측 가능성이라는 코드의 본질적인 가치는 변하지 않는다. 책에서 보여준 리팩토링 과정을 따라가며 느꼈던 즐거움처럼, 앞으로 마주할 레거시 코드나 혹은 내가 막 작성한 코드라도 조금 더 나은 상태로 만들어 동료에게 전달해야겠다. 그리고 나도 언젠가 오픈소스에 기여하며 더 넓은 세상의 코드에 긍정적인 영향을 미치고 싶다.







24 changes: 24 additions & 0 deletions 16장/공예영.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## **📕 Ch16. SerialDate 리팩터링**

이번 장에서는 SerialDate 클래스를 리팩터링하는 과정을 보여줬다. 날짜와 관련된 로직은 복잡하고 오류 가능성이 높기 때문에, 작은 개선도 코드 품질과 유지보수성에 큰 차이를 만든다.

### 1. 거대한 클래스 쪼개기

SerialDate는 너무 많은 역할을 떠안고 있었다. 날짜 계산, 포맷 변환, 상수 정의 등 서로 다른 책임을 한 클래스에서 처리하다 보니 코드가 읽기 어렵고 테스트도 힘들었다.<br/>
리팩터링은 단일 책임 원칙(SRP)을 기준으로 기능을 분리하는 것에서 시작한다. 예를 들어, 날짜 계산은 전용 유틸 클래스로 이동하고, 상수는 Enum으로 대체한다. 이렇게 하면 클래스 간 의존이 줄고 테스트도 간단해진다.

### 2. 매직 넘버 대신 의미 있는 상수

날짜 연산에는 “1월=1, 12월=12” 같은 매직 넘버가 반복된다. 이 장에서는 이를 Month.JANUARY, Month.DECEMBER 같은 Enum으로 치환한다. <br>
이는 가독성을 높이고 잘못된 값이 들어오는 것을 컴파일 단계에서 방지하여 오류를 사전에 줄일 수 있다.

### 3. 테스트로 신뢰성 확보하기

날짜는 예외 케이스가 많다. 윤년, 월 말일, 다른 달 간의 계산 같은 문제는 꽤나 복잡하다. 이 장에서는 리팩터링 전후의 결과를 비교하는 단위 테스트를 통해 동작을 검증한다. <br/>
테스트는 리팩터링을 뒷받침하는 안전망 역할을 한다.

### 4. 점진적 개선의 힘
SerialDate의 리팩터링은 한 번에 거대한 수술을 하는 방식이 아니라 작은 단위로 나눠 점진적으로 진행된다. 한 메서드, 한 책임, 한 상수부터 차근차근 개선한다. 이는 유지보수와 협업에서 매우 현실적이고 효과적인 방법론이다.

### 마무리
최근 외주 프로젝트에서 날짜 관련 복잡한 로직을 짜며 코드가 매우 복잡해졌다.. 당시엔 기능 구현을 우선으로 두었지만,이제는 여기서 배운 클린코드 원칙을 적용해서 테스트 코드를 작성 후 차근차근 리팩토링해보아야겠다!
53 changes: 53 additions & 0 deletions 17장/공예영.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
### 📕Ch 17. 냄새와 휴리스틱

마틴 파울러의 코드 냄새 + 클린코드 저자의 휴리스틱 목록

### 주석
- 변경 이력 등 다른 시스템에 저장할 정보를 주석으로 남기지 마라. 보통 작성자, 최종 수정일, SRP 번호 등 메타 정보만 넣는다.
- 쓸모 없는 주석은 재빨리 삭제하라.
- 코드와 중복되는 주석은 제거하라.
- 주절대지 말고, 당연한 소리 반복하지 말고, 간결하고 명료하게
- 주석으로 처리된 코드는 즉각 삭제해버려라. 두려워 하지 마라

### 환경
- 한번에 빌드하고, 한번에 테스트해야한다.

### 함수
- 인수 개수는 작을 수록 좋다.
- 플래그 인수는 피해라. 플래그는 함수가 여러 기능을 수행한다는 명백한 증거다.
- 아무도 호출하지 않는 함수는 과감히 삭제하라.

### 일반
- 당연한 동작을 구현하라. 최소 놀람의 원칙에 의거해 함수는 프로그래머가 당연히 여길 만한 동작과 기능을 제공해야 한다. 그래야 추상화의 의미가 있다.
- 경계를 올바르게 처리하라. 직관에 의존하지 말고 모든 경계와 구석진 곳을 테스트하는 테스트 케이스를 작성하라.
- 안전 절차를 지켜라. 컴파일러 경고 일부를 무시하면 빌드는 쉬워질지 몰라도 자칫 끝없는 디버깅에 시달린다.
- DRY 원칙. 중복을 발견할때마다 추상화할 기회로 간주하라.
- 올바른 추상화 수준. 기초 클래스는 구현 정보에 무지해야 한다.
- 잘 정의된 모듈은 인터페이스가 아주 작으며 결합도가 낮다.
- 변수와 함수는 가깝게
- 구현 방식과 이름에 일관성있게
- 변수, 상수, 함수를 당장 편한 위치에 넣지 마라. 게으르고 부주의한 행동이다.
- 계산을 여러 단계로 나누고 서술적인 변수 이름을 사용하라.
- 논리적 의존성을 물리적으로 드러내라
- 조건을 캡슐화하라
- 부정 조건을 피하라
- 경계조건을 캡슐화하라

### 이름
- 서술적인 이름을 사용하라.주석보다 강력하다.
- 적절한 추상화 수준에서 이름을 선택하라. 구현을 드러내느 이름은 피하라.
- 이름으로 부수 효과를 설명하라.

### 테스트
- 충분한 테스트케이스
- 커버리지 도구 사용하기
- 사소한 테스트 건너뛰지 마라
- 불분명한 요구사항은 테스트 케이스를 주석으로 처리하라
- 경계 조건, 버그 주변은 철저히 테스트
- 실패 패턴을 살펴라. 테스트 커버리지 패턴을 살펴라.
- 테스트는 빨라야한다.

### 마무리
마무리 장으로 우리가 실무에서 쉽게 간과하는 습관들을 되짚어 준다.
중복 제거(DRY), 긍정적이고 간결한 표현, 경계 조건을 명확히 처리하는 습관 등 바로 실천할 수 있고, 해야하는 원칙들이다. 또한 “쓸모없는 것은 과감히 지워라”라는 메시지는, 코드를 쌓아두기보다 끊임없이 정리하고 개선하는 태도가 중요함을 일깨워준다.
앞으로 코드를 작성할 때, 기능 구현에서 끝내지 않고 냄새와 휴리스틱의 목록을 스스로 점검하며 리팩터링하는 습관을 길러야겠다. 코드 품질을 높이고 동료와의 협업을 원활하게 하며 미래의 나 자신에게도 큰 선물이 될 것이다.!!