> For the complete documentation index, see [llms.txt](https://wonjoon.gitbook.io/joons-til/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wonjoon.gitbook.io/joons-til/books/the-pragmatic-programmer/3-basic-tools.md).

# #3 Basic Tools

### 💻 실용주의 프로그래머: Topic 16 일반 텍스트의 힘 (The Power of Plain Text)

***

#### 1. 핵심 개념 — “지식을 가장 오래 보존하는 형태”

> Tip 25. **지식을 일반 텍스트로 저장하라.**

프로그래머가 다루는 재료는 나무나 철이 아니라 **지식**이다.\
이 지식을 설계, 구현, 테스트, 문서로 표현하는데\
그 **표현의 포맷이 곧 지식의 수명**을 결정한다.

가장 단순하지만 가장 강력한 형식 — **일반 텍스트(plain text)**.\
바이너리 포맷(binary format)은 사라져도,\
텍스트는 시대를 넘어 살아남는다.

***

#### 2. 왜 일반 텍스트인가

바이너리 데이터는

* 읽는 사람에게 의미가 없고
* 전용 애플리케이션 없이는 해석할 수 없으며
* 시간이 지나면 해독할 방법조차 사라진다.

반면 **일반 텍스트는 그 자체로 의미를 지니며**,\
누구나, 어떤 환경에서도 읽고 이해할 수 있다.\
즉, 텍스트는 "데이터가 데이터를 만드는" 재료이다.

***

#### 3. 일반 텍스트의 정의

> “인쇄 가능한 문자로 이루어져 있고,\
> 정보 전달에 적합한 형태를 갖춘 데이터.”

즉, 간단한 목록도 텍스트이며,\
복잡한 설정 파일도 텍스트일 수 있다.

```txt
* 우유
* 양파
* 커피
```

혹은 이렇게 구조화된 형태일 수도 있다:

```txt
<Field1>id=467abe</Field1>
```

이해할 수 있는 텍스트는 곧 **사람과 시스템이 소통할 수 있는 데이터**다.

***

#### 4. 일반 텍스트의 힘

**(1) ✅ 지속성 (Durability)**

* 시간이 지나도 읽을 수 있다.
* 도구나 플랫폼이 바뀌어도 손실되지 않는다.
* 고대의 종이 문서처럼, 가장 오래 살아남는 디지털 형태다.

**(2) ⚙️ 이식성 (Portability)**

* 운영체제, 언어, 프레임워크에 무관하다.
* 유닉스 철학의 기본 단위(입출력 스트림, 설정, 로그 등)는 모두 텍스트다.

**(3) 🔍 가시성 (Transparency)**

* 디버깅이 쉽고, diff/grep 등 표준 도구로 바로 분석할 수 있다.
* 바이너리와 달리 "무엇이 변했는지"를 한눈에 볼 수 있다.

**(4) 🧰 도구 활용성 (Tooling Power)**

* 전 세계 거의 모든 개발 도구(VCS, 에디터, CLI 등)가 텍스트를 전제로 한다.
* 버전 관리, 검색, 백업, 배포 등 모든 자동화에 즉시 통합 가능.

***

#### 5. 일반 텍스트의 예시

| 도메인  | 예시                                  | 설명             |
| ---- | ----------------------------------- | -------------- |
| 설정   | `.env`, `.properties`, `nginx.conf` | 단순 키-값 기반 구성   |
| 데이터  | `.csv`, `.json`, `.yaml`, `.xml`    | 범용적, 인간 가독성 유지 |
| 로그   | `app.log`                           | 텍스트 기반 분석 가능   |
| 프로토콜 | `HTTP`, `SMTP`, `DNS`               | 모두 일반 텍스트로 정의됨 |

즉, **인터넷의 근본도 텍스트다.**

***

#### 6. 일반 텍스트의 실무적 장점

**🔒 “지원 중단에 대한 보험”**

* 오래된 시스템이 사라져도, 텍스트 파일은 남는다.
* 애플리케이션은 죽더라도 **데이터는 살아남는다.**
* 심지어 의미를 일부라도 복원할 수 있다.

**🧩 “기존 도구와 호환”**

* diff, grep, awk, sed, vim, git 등\
  모든 표준 유닉스 도구와 즉시 연동 가능.

**🧪 “더 쉬운 테스트”**

* 테스트 데이터나 결과를 텍스트로 출력하면,\
  스크립트로 자동 비교 및 분석 가능.

**🌐 “최소 공통분모로서의 표준”**

* 다양한 시스템이 얽힌 환경에서도\
  **텍스트만은 유일하게 모두 이해할 수 있는 표준 언어**다.

***

#### 7. 유닉스 철학과 일반 텍스트

> “작고 단순한 도구들이 텍스트를 주고받으며 협력한다.”

유닉스는 모든 것을 **텍스트 스트림으로 처리**하도록 설계됐다.\
이 덕분에 grep, cat, awk 같은 기본 명령으로\
복잡한 파이프라인을 구성할 수 있다.

```bash
grep -r "backup" /etc
```

이런 명령 한 줄로 시스템 전체를 탐색할 수 있는 이유는,\
**모든 데이터가 텍스트로 표현되어 있기 때문**이다.

***

#### 8. 도전 과제 — “데이터베이스를 텍스트로 생각하라”

> 도전해 볼 것 💡

* 단순한 주소록(이름, 전화번호 등)을 일반 텍스트 기반으로 설계하라.
* XML/JSON 버전을 만들어보고, 일반 텍스트 버전으로 바꿔보라.
* 이 둘을 diff로 비교해보고 어떤 게 더 명확한지 느껴보라.
* 텍스트 구조로 바꿀 때 **버전 관리/확장성/이해도**의 변화를 관찰하라.

***

#### 9. 핵심 메시지

* **텍스트는 지식의 최소 단위이자, 기술의 공통어다.**
* 바이너리는 시스템에 종속되지만,\
  **텍스트는 세대를 초월한다.**
* 우리는 언젠가 코드를 잃을 수 있지만,\
  **텍스트를 잃지 않으면 지식을 잃지 않는다.**

***

> \*\*일반 텍스트(plain text)\*\*는\
> “시간과 시스템을 넘어 지식을 보존하는 가장 강력한 포맷”이다.\
> *“모든 것은 텍스트로부터 온다.”*

### 💻 실용주의 프로그래머: Topic 17 셸 가지고 놀기 (Play with Shells)

***

#### 1. 핵심 개념 — “셸은 프로그래머의 작업대다”

모든 목수에게 튼튼한 작업대가 필요하듯,\
프로그래머에게는 **셸(Shell)** 이 작업의 중심이 된다.

셸은 단순히 명령을 입력하는 도구가 아니라,\
**작업 환경을 자동화하고 지식을 도구화하는 인터페이스**다.

***

#### 2. 셸의 본질 — “명령의 힘을 사용하라”

> Tip 26. **명령어 셸의 힘을 사용하라.**

셸은 GUI보다 느려 보이지만,\
실제론 더 유연하고 반복 작업에 강력하다.

GUI는 “WYSIWYG (What You See Is What You Get)”\
하지만 셸은 “WYSIAYG (What You See Is All You Get)” —\
즉, 눈에 보이는 게 전부다.\
셸은 **보이지 않는 내부 세계까지 제어할 수 있다.**

***

#### 3. 셸을 사용하는 이유

| GUI             | 셸                 |
| --------------- | ----------------- |
| 직관적이지만 반복작업에 약함 | 반복, 자동화에 최적       |
| 마우스 조작 중심       | 텍스트 조합 중심         |
| 환경 이식성 낮음       | 대부분의 시스템에 존재      |
| 한정된 기능          | 무한한 조합 가능 (파이프라인) |

결국 셸은 **자동화, 반복, 실험, 스크립팅**의 핵심 도구다.

***

#### 4. 셸의 핵심 기능과 실무 팁

**⚙️ (1) 파이프라인과 명령 조합**

셸은 간단한 명령들을 `|` 로 이어서\
복잡한 작업을 한 줄로 자동화할 수 있다.

```bash
grep "^import" *.java | sed -e 's/import //;s/;//' | sort -u > list
```

→ 수천 줄의 자바 코드에서 import된 패키지 목록을 추출해 파일로 저장.\
IDE에서 불가능한 일도, 셸 한 줄로 가능하다.

***

**🎨 (2) 색상 조합 및 프롬프트 설정**

자신의 셸을 꾸며라.

* 색상 테마, 디렉터리 경로, 버전 상태, 시간 등을 표시
* 현재 작업 맥락을 즉시 파악할 수 있게 해줌

```bash
export PS1="\u@\h:\w$ "
```

***

**🪄 (3) 별칭(alias)과 셸 함수**

반복되는 명령을 간소화하라.

```bash
alias apt-up='sudo apt-get update && sudo apt-get upgrade'
alias rm='rm -iv'   # 삭제 전 확인 추가
```

작업 효율을 높이고, 실수로 인한 파괴적 명령을 예방한다.

***

**🔄 (4) 명령 자동 완성**

셸은 대부분 **자동 완성(tab completion)** 기능을 제공한다.\
명령뿐 아니라 **파일명, 옵션, 디렉터리**까지 자동 완성할 수 있다.\
심지어 Zsh, Fish 같은 고급 셸은 AI 수준의 자동 완성도 가능하다.

***

**🧩 (5) 스크립트화로 반복 제거**

자주 수행하는 작업은 스크립트로 만들어라.\
예를 들어, 로그를 정리하거나 빌드를 수행하거나\
데이터를 파싱하는 일은 `.sh`로 만들어두면 된다.

```bash
#!/bin/bash
cd ~/projects
git pull
./gradlew build
```

***

#### 5. 셸을 자신의 것으로 만들어라

> “목수가 자신의 작업대를 세상에 맞추는 게 아니라,\
> 작업대를 자기 몸에 맞추듯이 개발자도 셸을 자신에게 맞춰야 한다.”

**☑️ 추천 셸 커스터마이징**

* **색상 테마:** `oh-my-zsh`, `powerlevel10k`
* **자동 완성:** `zsh-autosuggestions`, `fzf`
* **명령 기록 탐색:** `ctrl + r`
* **프로파일 관리:** `.bashrc` 또는 `.zshrc` 편집

***

#### 6. GUI와 셸의 관계

GUI는 효율적이지만 **한계가 명확**하다.\
시각적 피드백은 빠르지만,\
**대규모 자동화, 원격 서버, 로그 분석** 같은\
시스템 수준 작업에는 셸이 절대적이다.

> GUI는 결과를 보여주지만,\
> 셸은 결과를 *만드는* 도구다.

***

#### 7. 도전 과제

> **“손을 마우스에서 떼라.”**

* GUI에서 반복하는 작업 중 자동화 가능한 것이 있는가?\
  (예: 빌드, 파일 이동, 로그 정리 등)
* 새 환경(서버, CI/CD 등)에서 어떤 셸이 쓰이는지 확인하라.
* 다른 셸(bash, zsh, fish)을 직접 사용해보고 차이를 비교하라.

***

> **셸(Shell)** 은 프로그래머의 작업대이자,\
> 세상을 조립하는 도구다.\
> *“마우스보다 빠른 손, 명령보다 강한 자동화.”*

### 💻 실용주의 프로그래머: Topic 18 파워 에디팅 (Power Editing)

***

#### 1. 핵심 개념 — “에디터는 손의 연장이다”

> Tip 27. **에디터를 유창하게(fluently) 쓸 수 있게 하라.**

프로그래머의 주된 재료는 **텍스트**다.\
즉, 텍스트를 조작하는 능력이 곧 생산성이다.

에디터는 단순한 작성 도구가 아니라\
**사고와 코드가 만나는 인터페이스**,\
그리고 **손과 두뇌를 이어주는 가장 중요한 작업 환경**이다.

***

#### 2. 왜 에디터를 유창하게 써야 할까?

* 한 에디터를 **20시간**만 더 잘 사용해도 생산성이 4% 오른다.
* 하루 8시간씩 1년 동안 일한다고 하면, 이는 **한 달치 업무 시간에 해당**한다.

즉, 에디터 숙련도는 **곧 연봉과 프로젝트 속도에 직결되는 기술**이다.

***

#### 3. 유창하다는 것은 무엇인가?

> “유창함이란, 손이 생각보다 먼저 움직이는 상태다.”

다음 중 절반 이상을 빠르게 수행할 수 있다면 당신은 이미 숙련자다.

* 단어, 줄, 문단 단위로 커서 이동 및 선택
* 블록 복사, 잘라내기, 붙여넣기
* 들여쓰기 자동 정렬(`auto-indent`)
* 코드 변경 시 즉시 리팩터링
* 정규식 기반 검색/치환
* 여러 줄 동시 편집(multi-cursor)
* 테스트 실행/결과 확인
* 현재 프로젝트 오류 탐색

> “이 모든 걸 마우스 없이 수행할 수 있는가?”\
> 만약 아니오라면 — 아직 잠재력이 있다.

***

#### 4. 유창해지는 법 — “생활 습관처럼 익혀라”

**☑️ ① 에디터의 모든 명령어를 ‘조금씩’ 배워라**

한 번에 다 익히려 하지 말고,\
매일 **하루 한 가지 단축키**를 습득하라.\
일주일이면 완전히 손에 익는다.

**☑️ ② 반복적인 동작은 자동화하라**

* 코드 포매팅
* 주석 정리
* import 정렬
* 테스트 실행\
  이런 단순 반복은 에디터 매크로나 확장 기능으로 자동화하라.

**☑️ ③ “불편함”을 느낄 때마다 학습하라**

무언가 귀찮다고 느껴질 때,\
“이걸 더 쉽게 할 방법이 없을까?”라고 자문하고 찾아라.\
그 순간이 학습의 기회다.

***

#### 5. 에디터 성장시키기 — “당신의 도구를 확장하라”

**💡 확장 기능(Plugins)**

강력한 에디터는 기본 기능만으로 충분하지만,\
진짜 효율은 **확장(extensions)** 에서 나온다.

예를 들어:

* VS Code: Prettier, GitLens, Code Runner
* IntelliJ: AceJump, Key Promoter X, Rainbow Brackets
* Vim: NERDTree, Fugitive, Telescope

> “필요한 기능을 직접 만들어야 한다면, 그것이 바로 성장의 신호다.”

**💡 커스터마이징**

* 단축키 재매핑 (예: `Ctrl+D` → 줄 복사)
* 키맵 통합 (VSCode ↔ IntelliJ ↔ Vim 키스타일 맞추기)
* 특정 파일 확장자에 따라 설정 자동 적용

***

#### 6. 유창함과 자유

유창함은 단순한 속도 향상이 아니라 **몰입(flow)** 을 만든다.\
손이 코드보다 느리면 생각이 끊기고,\
손이 따라가면 생각이 흐른다.

> “에디터는 코드를 치는 도구가 아니라, 생각을 흐르게 하는 도구다.”

숙련된 에디터 사용자는 **생각하는 속도 = 타이핑 속도**로 작업한다.\
이때 생산성은 단순히 배로 오르는 것이 아니라, **질적으로 상승한다.**

***

#### 7. 도전 과제

* 🚀 “마우스를 전혀 쓰지 않고 하루 일과를 마칠 수 있는가?”
* 🧠 “에디터 내에서 바로 테스트를 실행하고, 결과를 확인할 수 있는가?”
* 🧩 “반복 작업을 줄이기 위해 매크로나 스니펫을 작성한 적이 있는가?”
* 🛠️ “에디터의 플러그인 API를 통해 직접 기능을 만들어본 적이 있는가?”

***

#### 8. 마스터를 위한 습관

| 단계 | 습관              | 예시                                   |
| -- | --------------- | ------------------------------------ |
| 초급 | 단축키 외우기         | Ctrl + D, Ctrl + /, Ctrl + Shift + F |
| 중급 | 자동화하기           | 매크로, 스니펫, 정규식 치환                     |
| 고급 | 확장 만들기          | JetBrains Plugin, VSCode Extension   |
| 장인 | 도구를 넘어 시스템을 만든다 | 에디터를 IDE화, 개인 개발 환경 구축               |

***

> **“에디터 유창함은 생산성의 시작이자, 몰입의 문턱이다.”**\
> *“손이 코드를 가로막지 않게 하라.”*

### 💻 실용주의 프로그래머: Topic 19 버전 관리 (Version Control)

***

#### 1. 핵심 개념 — “기억은 짧고, 버전 관리는 길다”

> Tip 28. **언제나 버전 관리 시스템을 사용하라.**

인간의 기억은 불완전하다.\
실수를 되돌릴 수 있는 **Undo 키**는 일시적이지만,\
**VCS(Version Control System)** 은 프로젝트의 역사를 통째로 되돌린다.

버전 관리는 단순한 ‘백업’이 아니라,\
**시간을 통제하는 기술**이다.

***

#### 2. 버전 관리의 의미

프로그래머에게 버전 관리 시스템은\
코드뿐 아니라 *모든 지적 자산의 타임머신*이다.

* 실수를 용서하고 되돌릴 수 있다.
* 변경의 이유와 맥락을 추적할 수 있다.
* 협업 시 충돌을 조정하고, 분기(branch)된 아이디어를 실험할 수 있다.
* 배포와 테스트, 품질 관리의 기반이 된다.

> “VCS는 단순한 코드 저장소가 아니라,\
> 프로젝트 전체의 **시간적 스냅샷**이다.”

***

#### 3. 소스 코드에서 시작하지만, 거기서 끝나지 않는다

VCS는 단순히 소스 코드를 추적하기 위한 것이 아니다.\
문서, 빌드 스크립트, 설정 파일, 심지어 디자인 산출물까지도 관리할 수 있다.

즉, **소프트웨어의 모든 산출물**을\
시간축 위에서 관리할 수 있는 도구다.

```
src/
 ├─ main/
 ├─ test/
 ├─ docs/
 ├─ scripts/
 └─ .git/
```

***

#### 4. 왜 VCS가 중요한가

**⚙️ (1) 실수를 되돌릴 수 있다**

과거의 버전으로 돌아가거나, 특정 시점의 코드를 복원할 수 있다.\
이는 곧 “Undo”를 프로젝트 단위로 확장한 것이다.

**👥 (2) 협업을 가능하게 한다**

여러 사람이 동시에 작업하더라도 충돌을 조정할 수 있다.\
브랜치(branch)로 나누어 개발하고,\
merge로 통합한다.

**🧠 (3) 프로젝트의 진화를 기록한다**

누가, 언제, 왜 코드를 바꿨는지 명확히 알 수 있다.\
이 정보는 **리뷰, QA, 디버깅, 회고** 등 모든 활동의 근간이다.

**🏗️ (4) 자동화의 기반이 된다**

빌드, 테스트, 배포 파이프라인은\
VCS에 기록된 이력과 연계되어야만 일관성을 유지할 수 있다.

***

#### 5. 브랜치의 힘 — “실험할 자유를 주는 도구”

> “브랜치는 곧 평행우주다.”

VCS의 진짜 가치는 **브랜치(Branch)** 에 있다.\
새로운 기능을 시도하거나 리팩터링을 해볼 때,\
기존 코드를 위험에 빠뜨리지 않고 실험할 수 있다.

```bash
git checkout -b feature/new-api
# 실험 완료 후
git merge feature/new-api
```

다른 브랜치의 작업과 병행할 수 있으며,\
충돌은 병합 시점에서 해결된다.\
브랜치는 결국 **팀 협업을 위한 실험 공간**이다.

***

#### 6. 버전 관리의 활용 범위

> “버전 관리는 소스 코드만의 것이 아니다.”

다음과 같은 것들도 버전 관리하라:

* 홈 디렉터리 설정(`.zshrc`, `.vimrc`)
* 서버 설정 스크립트(`ansible`, `terraform`)
* CI/CD 파이프라인 정의 파일
* 개발 환경 자동 설정(`brew bundle`, `package.json`)
* 프로젝트 문서, 테스트 케이스, 디자인 명세

이들은 모두 **팀의 지식 자산**이며,\
VCS에 남길 때 비로소 **재현 가능한 환경**이 된다.

***

#### 7. 개인 개발자에게도 필요한 이유

“혼자 하는 프로젝트라서 버전 관리가 필요 없다고?”\
그렇지 않다.

* 과거 버전으로 돌아가야 하는 상황은 누구에게나 생긴다.
* 백업 이상의 의미로, **작업 기록과 실험의 추적성**을 제공한다.
* VCS를 쓰면 **작업 중단 → 복귀**가 자연스러워진다.

> “혼자서라도 버전 관리를 쓰지 않으면,\
> 협업할 준비가 되지 않은 것이다.”

***

#### 8. 현대적 버전 관리 — “프로젝트 허브로서의 Git”

오늘날 대부분의 프로젝트는 **Git + 중앙 원격 저장소(GitHub, GitLab, Bitbucket 등)** 구조를 갖는다.\
이는 단순 저장소를 넘어 **협업 허브** 역할을 한다.

**🔧 주요 기능**

* Pull Request / Merge Request 기반 협업
* 자동화된 테스트 및 배포 파이프라인
* 코드 리뷰 및 승인 제도
* 이슈 관리 및 칸반 보드
* 변경 알림 및 팀 커뮤니케이션

> Git은 이제 “버전 관리 도구”가 아니라\
> \*\*“팀의 뇌”\*\*다.

***

#### 9. 실용주의적 조언

* **항상 버전 관리 시스템을 사용하라.**\
  (프로토타입이든, 개인 실험이든 상관없다.)
* **모든 것을 커밋하라.**\
  코드뿐 아니라, 빌드 스크립트, 문서, 설정 파일까지.
* **버전 관리의 단위를 ‘변경의 의미’로 삼아라.**\
  즉, 커밋은 “작업 단위”가 아니라 “의미 단위”로 남겨라.
* **브랜치를 두려워하지 마라.**\
  실패를 되돌릴 수 있다는 건, 더 자유롭게 시도할 수 있다는 뜻이다.

***

#### 10. 도전 과제

* ⚡ 예상치 못한 사고가 났을 때, **어떻게 복원할지** 연습하라.
* 🧱 현재 사용 중인 모든 VCS 기능을 점검하라.\
  (브랜치 전략, PR 템플릿, CI 연계 등)
* 💾 설정 파일이나 개인 환경(dotfiles)을 Git으로 관리해보라.
* 🔁 “Git 없이 이 프로젝트를 복구할 수 있는가?”를 자문하라.

***

> **버전 관리(VCS)** 는 실수를 되돌리는 기술이자,\
> 팀의 지식을 축적하는 메모리다.\
> *“Undo를 넘어서, 역사를 기록하라.”*

### 💻 실용주의 프로그래머: Topic 20 디버깅 (Debugging)

***

#### 1. 핵심 개념 — “디버깅은 고통이 아니라 탐구다”

> “참으로 고통스러운 일입니다.\
> 자신이 겪는 어려움을 보고는 알게 되죠.\
> 다른 누구도 아닌 바로 자신이 문제를 만들었다는 걸.”\
> — 소포클레스 (Sophocles)

디버깅은 단순한 버그 제거가 아니라\
**문제 해결을 통해 시스템을 이해하는 과정**이다.

‘버그’(bug)는 1940년대 COBOL의 창안자 **그레이스 호퍼(Grace Hopper)** 가 실제로\
컴퓨터 회로에 낀 ‘벌레’를 발견하며 유래된 말이지만,\
오늘날의 버그는 훨씬 더 복잡하다 —\
**기술적 문제와 인간적 오해가 얽힌 미로**다.

***

#### 2. 디버깅의 심리 — “비난보다 해결”

> Tip 29. **비난 대신 문제를 해결하라.**

버그를 발견했을 때 중요한 건 “누가 잘못했는가”가 아니라,\
“왜 그런 결과가 나타났는가”이다.

비난은 감정의 소모고,\
**해결은 지식의 축적**이다.

디버깅은 문제를 풀어가는 과정이지, 범인을 찾는 수사가 아니다.\
냉정하고 체계적으로 문제의 본질을 밝혀야 한다.

***

#### 3. 디버깅 사고방식 — “가장 속이기 쉬운 사람은 자기 자신이다”

> Tip 30. **당황하지 말라.**

버그는 대부분 우리가 만든 코드에 있다.\
다른 사람의 탓, 환경 탓, 라이브러리 탓을 하기 전에\
**“내가 뭘 잘못했을까?”** 를 먼저 물어야 한다.

* “이건 불가능해!”라는 말은 디버깅에서 가장 위험한 말이다.
* 버그는 언제나 **가능한 이유가 있었기 때문에 존재한다.**

> 디버깅의 제1법칙: **침착하고 의심하라.**

***

#### 4. 디버깅 절차 — “체계적으로 사고하라”

**(1) 문제를 재현하라**

> Tip 31. **코드를 고치기 전, 실패하는 테스트부터.**

가장 좋은 디버깅은 **문제를 재현할 수 있는 테스트를 만드는 것**이다.\
재현이 되지 않는 버그는 고칠 수도, 검증할 수도 없다.

**(2) 증상과 원인을 구분하라**

* 증상(symptom): 프로그램이 보이는 현상
* 원인(cause): 그 현상을 일으킨 실제 이유

이 둘을 혼동하면, 표면적인 문제만 고치고 근본은 남는다.

**(3) 사실 기반으로 접근하라**

추측하지 말고, **관찰·로그·트레이스**로 데이터에 근거해 분석하라.\
“아마 이럴 거야”가 아니라 “이 로그에 따르면 이 시점에 멈췄다”가 되어야 한다.

***

#### 5. 실마리 찾기 — “눈보다 로그”

* **실행 전:** 컴파일러 경고를 무시하지 마라.
* **실행 중:** 로그와 트레이스를 통해 “어디까지 실행되었는가”를 확인하라.
* **실행 후:** 스택 트레이스와 에러 메시지를 반드시 읽어라.

  > Tip 32. **그놈(damn) 오류 메시지 좀 읽어라.**

엔지니어는 자신의 코드가 멈춘 이유를 **메시지가 이미 알려줬는데도**\
읽지 않아 시간을 낭비한다.\
경험 많은 개발자는 메시지를 읽는 것만으로도 절반의 문제를 해결한다.

***

#### 6. 주요 디버깅 전략

**🧩 ① 입력값에 따라 바뀌는지 확인하라**

특정 데이터 세트에서만 문제가 발생한다면,\
**입력값이 버그를 유발하는 핵심 단서**다.\
테스트 데이터, 경계값, 인코딩 문제를 점검하라.

**🔁 ② 릴리스 간의 차이를 비교하라**

이전 버전에는 없던 문제가 발생했다면,\
“언제부터 문제였는가”를 좁혀가며 원인을 찾아라.\
→ **이진 탐색(binary search)** 방식으로 릴리스를 추적하면 효율적이다.

**🧠 ③ 로깅과 트레이싱을 습관화하라**

트레이싱은 **현재 시스템 상태를 관찰**하는 기본 수단이다.\
실시간 로그를 통해 호출 흐름, 인자값, 상태 변화를 추적하라.

**🗣️ ④ 고무 오리 디버깅(Rubber Duck Debugging)**

> Tip 33. **“select”는 망가지지 않았다.**

누군가에게(혹은 고무 오리에게) 문제를 설명하라.\
말로 정리하는 과정에서 사고가 명확해지고,\
대부분의 버그는 그 설명 도중에 스스로 드러난다.

***

#### 7. 흔한 실수

| 잘못된 태도           | 올바른 태도           |
| ---------------- | ---------------- |
| “그럴 리 없어!”       | “그럴 리 있다고 가정하자.” |
| 로그 안 남기고 코드부터 수정 | 로그를 먼저 남기고 테스트   |
| “남의 코드 탓이야”      | 내 코드와 환경부터 점검    |
| 스택 트레이스 무시       | 메시지와 실행 경로 추적    |
| 임시방편 수정          | 근본 원인 해결 후 리팩터링  |

***

#### 8. 디버깅의 구조적 접근

> Tip 34. **가정하지 말라. 증명하라.**

모든 디버깅은 **가정의 검증 과정**이다.\
“이 함수는 잘 동작할 거야”라는 생각 대신,\
“이 함수가 실제로 동작하는지 테스트해보자”로 바꿔라.

의심 가는 부분을 작은 단위 테스트로 검증하며,\
한 단계씩 원인을 좁혀가는 것이 핵심이다.

***

#### 9. 디버깅 체크리스트

* 문제를 다른 사람에게 설명할 수 있는가?
* 해당 버그를 테스트로 재현할 수 있는가?
* 에러 메시지를 해석했는가?
* 로그에 원인이 남아 있는가?
* 입력값이 의도대로 전달되었는가?
* 이 버그가 같은 조건에서 다른 곳에서도 발생하는가?
* 버그 수정 후, 다른 부작용이 생기지 않는가?

***

#### 10. 디버깅은 실용주의적 학습이다

디버깅은 “코드를 고치는 기술”이 아니라\
\*\*“시스템을 이해하는 학문”\*\*이다.

한 버그를 제대로 고친 개발자는,\
단순한 오류 해결을 넘어서 **시스템의 작동 원리와 인간의 실수를 동시에 이해한 사람**이 된다.

***

> **디버깅은 비난이 아닌 탐구이며, 증명 없는 확신은 적이다.**\
> *“가정하지 말고, 재현하고, 기록하라.”*

### 💻 실용주의 프로그래머: Topic 21 텍스트 처리 (Text Manipulation)

***

#### 1. 핵심 개념 — “모든 것은 결국 텍스트다”

실용주의 프로그래머는 나무를 다루는 목수처럼 **텍스트를 다루는 장인**이다.\
소스 코드, 설정 파일, 로그, 데이터 파일, 문서 등…\
모든 것은 결국 문자열로 표현된다.

따라서 진정한 프로그래머라면\
**텍스트를 자유롭게 변환·가공·추출할 수 있는 능력**을 가져야 한다.

> Tip 35. **텍스트 처리 언어를 익혀라.**

***

#### 2. 텍스트 처리 언어의 역할 — “도끼 대신 루터(router)”

저자는 텍스트 처리 언어를 **목수의 루터(router)** 에 비유한다.\
루터는 거칠고 무거운 나무를 정밀하게 다듬는 도구이고,\
텍스트 처리 언어도 마찬가지로\
기존 도구(셸, 에디터, IDE 등)로는 힘든 변형 작업을 빠르게 수행하게 해준다.

* 단순 치환, 패턴 검색, 문자열 분리 → 기본기
* 데이터 포맷 변환, 코드 자동 생성, 로그 분석 → 고급기

***

#### 3. 왜 필요한가 — “자동화와 확장의 언어”

텍스트 처리를 배우면 **단순 반복을 자동화**하고\
**시스템을 연결하는 파이프라인**을 구축할 수 있다.

> “프로젝트의 중요한 컴포넌트를 자동화하면 하루를 보내는 방식이 달라진다.”\
> — 브라이언 커니핸(Brian Kernighan) & 롭 파이크(Rob Pike)

예를 들어:

* 로그 파일에서 특정 패턴을 찾아 요약하기
* 설정 파일을 다른 포맷(YAML → JSON 등)으로 변환하기
* 코드 템플릿을 생성하거나 주석 자동화하기
* 빌드/배포/테스트 결과를 텍스트로 리포팅하기

***

#### 4. 주요 도구들

텍스트 처리에 특화된 언어 및 유틸리티는 다음과 같다:

| 종류             | 대표 예시                | 특징                        |
| -------------- | -------------------- | ------------------------- |
| **UNIX 기반 도구** | `grep`, `awk`, `sed` | 빠르고 단순하며 파이프라인과 잘 결합      |
| **스크립트 언어**    | Perl, Python, Ruby   | 정규식·파일 처리에 강력함            |
| **셸 조합 도구**    | Bash + jq + curl     | 작은 명령들을 이어붙여 강력한 워크플로우 생성 |

특히 `awk`와 `sed`는 “유닉스의 숨은 언어”로 불릴 만큼\
텍스트 가공에서 압도적인 성능을 보여준다.

***

#### 5. 철학적 관점 — “도구를 능숙히 다루면 세상이 달라진다”

텍스트 처리 언어는 단순 기술이 아니라 **enabling technology**,\
즉 **가능성을 확장하는 기술**이다.

도구 하나를 능숙히 다루면\
새로운 문제를 푸는 방식 자체가 바뀌고,\
기계적으로 반복되던 일에 **지적 효율성**을 부여한다.

> “30분을 쓰는 것보다 5분짜리 스크립트를 만드는 게 더 낫다.”

***

#### 6. 실전 예시 — 루비 빌드 시스템 ‘Rake’

이 책의 저자들은 책 출판 자동화를 위해 **루비(Ruby)** 와 **Rake** 를 활용했다.

**예시 1️⃣ 책 빌드 자동화**

* 각 장의 소스 파일을 읽어 PDF로 병합
* LaTeX 수식 렌더링 자동화
* 코드 예제 테스트 자동 실행

**예시 2️⃣ 웹사이트 갱신**

* 새로운 글 추가 → Rake 스크립트 실행
* HTML 템플릿 갱신 + 자동 업로드
* 검색 인덱스(index) 자동 재생성

> 즉, “코드·문서·사이트” 전부를 텍스트로 자동화했다.

***

#### 7. 실무 팁 — “모든 것은 텍스트로 저장하라”

* 설정, 스펙, 데이터, 스크립트는 가능하면 **텍스트 파일로 관리**하라.
* 이진 포맷보다 텍스트 포맷은 **가시성·검색성·버전 관리**가 훨씬 유리하다.
* 텍스트 포맷을 다루는 능력은 곧 **프로젝트 유지보수성**이다.

***

#### 8. 실습 과제 요약

| 번호        | 과제                 | 내용                                             |
| --------- | ------------------ | ---------------------------------------------- |
| **연습 11** | `.yaml → .json` 변환 | 설정 파일을 JSON 포맷으로 일괄 변환하는 스크립트 작성               |
| **연습 12** | 변수명 스타일 검사         | `camelCase` 사용 부분을 찾아 `snake_case` 로 변환하는 스크립트 |
| **연습 13** | 자동 백업              | 스타일 변환 시 백업 파일을 자동 생성                          |

이 과제들은 실제 현업에서도 매우 자주 등장하는 자동화 작업이다.

***

#### 9. 관련 항목

* **항목 16. 일반 텍스트의 힘** — 데이터는 텍스트일 때 가장 유연하다
* **항목 17. 셸 가지고 놀기** — 셸 스크립트는 텍스트 자동화의 기반

***

> **“텍스트를 다루는 능력은 개발자의 해방구다.”**\
> 반복 작업을 스크립트로 바꾸고, 데이터와 코드를 언어처럼 다뤄라.

### 💻 실용주의 프로그래머: Topic 22 엔지니어링 일지 (Engineering Journal)

***

#### 1. 핵심 개념 — “좋은 엔지니어는 기록한다”

> “생각하지 않으면 잊는다. 기록하지 않으면 사라진다.”

많은 훌륭한 엔지니어들은 늘 **수첩**을 들고 다닌다.\
아이디어, 실험, 회의 내용, 시행착오 — 무엇이든 적는다.\
그들은 이 습관을 **엔지니어링 일지(Engineering Journal)** 라 부른다.

이 일지는 단순한 메모장이 아니라,\
**자신의 사고를 저장하고 되돌아보는 시스템**이다.

***

#### 2. 일지의 목적 — “생각을 외부화하라”

우리가 하는 일 대부분은 “머릿속에서 일어나는 실험”이다.\
그러나 머릿속은 휘발성 메모리다.

생각을 적는 순간, **추상적인 사고가 구체화되고**,\
문제의 본질이 드러난다.

> “일지는 두 번째 뇌다.\
> 기록하는 순간, 문제의 절반은 이미 해결된다.”

***

#### 3. 일지를 쓰면 좋은 세 가지 이유

**(1) 🧠 기억보다 믿을 수 있다**

사람들은 “그때 뭐였더라?”라는 질문을 너무 자주 한다.\
하지만 일지를 쓰는 사람은 **사건의 맥락과 날짜, 의사결정의 근거**를 남긴다.\
예:

> “지난주 서버 이슈는 11/4 오전 2시에 배포된 버전에서 발생.\
> config.yml 수정 내용과 관련 있음.”

이 기록 하나가 미래의 수많은 디버깅 시간을 줄여준다.

***

**(2) 🔍 발상을 잃지 않는다**

작업 중 떠오른 아이디어, 해결되지 않은 문제, 실험 결과 등을\
즉시 적어두면, **다시 돌아올 수 있는 스냅샷**이 된다.

그 순간의 감정과 맥락까지 함께 남기면,\
훗날 같은 문제를 만났을 때 재현 가능한 사고의 근거가 된다.

***

**(3) 🧩 고무 오리 효과와 같다**

> Tip 34에서의 “고무 오리 디버깅”처럼,\
> 일지를 쓰는 행위는 **생각을 구조화하고 스스로 설명하는 과정**이다.

적는 동안, 머릿속의 혼란이 정리되고,\
“무엇을 모르는가”가 명확해진다.

***

#### 4. 어떻게 써야 하는가 — “도구보다 습관”

* 회의 중, 디버깅 중, 설계 중 언제든 떠오르는 것을 **바로 기록**하라.
* 포맷보다 **연속성**이 중요하다. (매일/매주 꾸준히)
* 전용 앱이 아니라 **아날로그 수첩이나 텍스트 파일**로도 충분하다.
* 기록할 때는 **감정, 상황, 의도**까지 남겨라.\
  예: “오늘 시도한 캐시 로직이 실패한 이유: TTL 계산 실수. 피로함 때문에 조건문을 놓침.”

***

#### 5. 기록의 활용 — “시간을 축적하는 기술”

일지는 단순한 히스토리가 아니라 **회고의 자산**이 된다.

* 과거의 시행착오에서 패턴을 발견하고,
* 현재의 결정을 검증하며,
* 미래의 후배나 팀원에게 지식을 전달할 수 있다.

> “일지를 남긴다는 것은, 당신의 경험을 시간 위에 저장하는 일이다.”

***

#### 6. 저자의 조언 — “수첩을 넘어, 사고의 기록으로”

저자들은 이렇게 말한다.

> “회의 중 메모하라.\
> 디버깅 중 변수의 변화를 적어라.\
> 실패와 배움을 기록하라.”

이런 습관은 엔지니어로서의 깊이를 만들어준다.\
글을 쓰는 행위 자체가 **생각을 명료하게 만드는 훈련**이기 때문이다.

***

#### 7. 현대적 확장 — “디지털 일지의 시대”

오늘날 일지는 단순 수첩을 넘어 **디지털 형태로 진화**했다.

* Notion, Obsidian, Logseq, VSCode Notebook
* Git commit log + PR description
* 일일 회고(Daily Retrospective)

이들은 모두 같은 목적을 가진다 —\
**사고의 흐름을 기록하여, 팀과 공유 가능한 지식으로 만든다.**

***

#### 8. 관련 항목

* **항목 13. 고무 오리 디버깅** — 말하는 순간 생각이 정리된다
* **항목 34. 가정하지 말라, 증명하라** — 기록은 검증의 시작이다

***

> **기록은 개발자의 메모리가 아니라, 사고의 증거다.**\
> *“생각을 적어라. 그래야 다시 꺼내 쓸 수 있다.”*
