# 코드 작성·변경 원칙과 모듈화

## 네 가지 원칙

| 원칙 | 한 줄 | 실천 |
|---|---|---|
| 먼저 생각한다 | 추측하지 않는다 | 가정을 밝힌다. 해석이 여러 가지면 고르지 말고 묻는다. 더 단순한 방법이 있으면 말한다 |
| 단순하게 | 요청받은 만큼만 | 요청에 없는 기능·추상화·설정 옵션을 넣지 않는다. 200줄을 50줄로 쓸 수 있으면 다시 쓴다 |
| 필요한 곳만 고친다 | 수술처럼 | 옆 코드·주석·서식을 "개선"하지 않는다. 기존 스타일에 맞춘다. 무관한 죽은 코드는 지우지 말고 알린다 |
| 목표로 검증한다 | 성공 기준부터 | 확인 가능한 목표를 정하고, 확인될 때까지 반복한다 |

> 시험 — **바뀐 모든 줄이 요청으로 곧장 이어지는가?** 아니라면 범위를 벗어난 변경입니다.

내가 바꾼 결과로 쓰이지 않게 된 import·변수·함수는 지웁니다. 원래 있던 죽은 코드는 요청이 없으면 그대로 둡니다.

## 파일 크기와 모듈화

| 파일 길이 | 할 일 |
|---|---|
| 300줄 초과 | 모듈 분리를 **검토**한다 |
| 500줄 초과 | 기능·책임별로 **반드시** 분리한다 |
| 목표 | 각 모듈 300줄 이하 |

- 분리할 때 **순환 참조**가 생기지 않게 합니다.
- 분리 기준은 "줄 수"가 아니라 **책임**입니다. 한 파일이 한 가지 일을 하게 나눕니다.

> 왜 — 한 파일에 여러 기능이 섞이면, 한 기능을 고칠 때 다른 기능이 깨지는지 알기 어렵고 로그·리뷰도 파일 단위로 나눌 수 없게 됩니다.

## 단일 출처(Single Source of Truth)

같은 값·같은 이름표를 여러 곳에서 쓰면 **한 곳에만 정의**하고 나머지는 그것을 읽습니다.

- 서버와 화면이 같은 상태 이름을 쓰면, 양쪽의 정의 파일을 **함께** 갱신합니다.
- 로그 경로, 알림 수신처, 표시명 같은 것은 정해진 한 모듈을 통해서만 만듭니다.

## 서버와 화면은 함께 확인한다

서버나 화면(클라이언트) 어느 한쪽을 고칠 때, **양쪽이 같은 동작을 하는지** 함께 확인합니다.

- 서버의 판정 조건을 바꾸면 → 화면의 표시·판정도 확인
- 화면의 표시 규칙을 바꾸면 → 서버가 그 상태를 실제로 만들어 내는지 확인

수정 후 "서버가 이 상태를 만들고, 화면이 그 상태를 이렇게 표시한다"를 **한 문장으로 설명할 수 있어야** 합니다. 설명이 안 되면 아직 한쪽만 본 것입니다.

## 조용히 다른 값으로 바꿔치지 않는다

값을 못 읽었을 때 **그럴듯한 다른 값으로 채우지 않습니다.** 없으면 없다고 경고합니다.

```js
// X — DB에서 수신처를 못 읽으면 관리자 번호로 대체
const to = readOwnerPhone() || ADMIN_PHONE;   // 로그엔 "보냄", 실제 수신자는 엉뚱한 곳

// O — 못 읽으면 빈 값 + 1회 경고
const to = readOwnerPhone();
if (!to) warnOnce('수신처 없음 — 호출 위치: ' + caller);
```

> 왜 — 실제 사례로, 고객에게 가야 할 알림이 관리자에게만 갔는데 로그에는 "발송함"으로 남아 몇 번이나 원인을 놓쳤습니다. **안 보낸 것보다 나쁩니다.**

부팅 시점에 한 번만 값을 읽어 고정해 버리는 코드(예: getter 를 구조분해로 받기)도 같은 함정을 만듭니다. 매번 읽어야 하는 값은 매번 읽습니다.

## 수정 이력은 소스가 아니라 이력 파일에

- 소스·문서 안에 `## 수정 이력` 블록을 **새로 넣지 않습니다.**
- 파일 상단에는 그 파일의 **역할 설명**만 둡니다.
- 작업 이력은 저장소의 이력 파일(예: `history.md`)과 커밋 메시지에 남깁니다.
- 기존 수정 이력 블록은 일괄 제거하지 않고, 그 파일을 실제로 고칠 때 함께 지웁니다.

이력 파일 한 줄 형식:

```
**2026-10-27 14:05:12** 예약세척 시작 전 취소 시 우유밀기 차단이 걸리던 판정 수정
```

- 날짜만이 아니라 **시분초까지** 적습니다.
- 라벨·스타일 등 **화면 표시만 바뀐 작업은 기록하지 않습니다.** 로직 변경만 기록합니다.

> 왜 — 파일마다 이력을 붙이면 금방 낡고, 같은 내용이 커밋 기록과 중복됩니다. 이력은 한곳에서 시간순으로 보는 편이 쓸모 있습니다.

## 설계를 먼저 갱신하고 구현한다

의미 있는 기능 추가·동작 변경·통신 명령 추가는 **설계 기록(명령 표·조건·순서)을 먼저 갱신**한 뒤, 그 기준으로 구현합니다. 설계 기록 없이 명령·게이트·주기 조회 로직만 추가하지 않습니다.
